Skip to content

Commit bbd7a6c

Browse files
xdarklightbebarino
authored andcommitted
clk: divider: Add re-usable determine_rate implementations
These are useful when running on 32-bit systems to increase the upper supported frequency limit. clk_ops.round_rate returns a signed long which limits the maximum rate on 32-bit systems to 2^31 (or approx. 2.14GHz). clk_ops.determine_rate internally uses an unsigned long so the maximum rate on 32-bit systems is 2^32 or approx. 4.29GHz. To avoid code-duplication switch over divider_{ro_,}round_rate_parent to use the new divider_{ro_,}determine_rate functions. Reviewed-by: Jerome Brunet <[email protected]> Signed-off-by: Martin Blumenstingl <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Stephen Boyd <[email protected]>
1 parent faa0e30 commit bbd7a6c

File tree

2 files changed

+67
-14
lines changed

2 files changed

+67
-14
lines changed

drivers/clk/clk-divider.c

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -343,16 +343,63 @@ static int clk_divider_bestdiv(struct clk_hw *hw, struct clk_hw *parent,
343343
return bestdiv;
344344
}
345345

346+
int divider_determine_rate(struct clk_hw *hw, struct clk_rate_request *req,
347+
const struct clk_div_table *table, u8 width,
348+
unsigned long flags)
349+
{
350+
int div;
351+
352+
div = clk_divider_bestdiv(hw, req->best_parent_hw, req->rate,
353+
&req->best_parent_rate, table, width, flags);
354+
355+
req->rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, div);
356+
357+
return 0;
358+
}
359+
EXPORT_SYMBOL_GPL(divider_determine_rate);
360+
361+
int divider_ro_determine_rate(struct clk_hw *hw, struct clk_rate_request *req,
362+
const struct clk_div_table *table, u8 width,
363+
unsigned long flags, unsigned int val)
364+
{
365+
int div;
366+
367+
div = _get_div(table, val, flags, width);
368+
369+
/* Even a read-only clock can propagate a rate change */
370+
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
371+
if (!req->best_parent_hw)
372+
return -EINVAL;
373+
374+
req->best_parent_rate = clk_hw_round_rate(req->best_parent_hw,
375+
req->rate * div);
376+
}
377+
378+
req->rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, div);
379+
380+
return 0;
381+
}
382+
EXPORT_SYMBOL_GPL(divider_ro_determine_rate);
383+
346384
long divider_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
347385
unsigned long rate, unsigned long *prate,
348386
const struct clk_div_table *table,
349387
u8 width, unsigned long flags)
350388
{
351-
int div;
389+
struct clk_rate_request req = {
390+
.rate = rate,
391+
.best_parent_rate = *prate,
392+
.best_parent_hw = parent,
393+
};
394+
int ret;
352395

353-
div = clk_divider_bestdiv(hw, parent, rate, prate, table, width, flags);
396+
ret = divider_determine_rate(hw, &req, table, width, flags);
397+
if (ret)
398+
return ret;
354399

355-
return DIV_ROUND_UP_ULL((u64)*prate, div);
400+
*prate = req.best_parent_rate;
401+
402+
return req.rate;
356403
}
357404
EXPORT_SYMBOL_GPL(divider_round_rate_parent);
358405

@@ -361,23 +408,23 @@ long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
361408
const struct clk_div_table *table, u8 width,
362409
unsigned long flags, unsigned int val)
363410
{
364-
int div;
365-
366-
div = _get_div(table, val, flags, width);
411+
struct clk_rate_request req = {
412+
.rate = rate,
413+
.best_parent_rate = *prate,
414+
.best_parent_hw = parent,
415+
};
416+
int ret;
367417

368-
/* Even a read-only clock can propagate a rate change */
369-
if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
370-
if (!parent)
371-
return -EINVAL;
418+
ret = divider_ro_determine_rate(hw, &req, table, width, flags, val);
419+
if (ret)
420+
return ret;
372421

373-
*prate = clk_hw_round_rate(parent, rate * div);
374-
}
422+
*prate = req.best_parent_rate;
375423

376-
return DIV_ROUND_UP_ULL((u64)*prate, div);
424+
return req.rate;
377425
}
378426
EXPORT_SYMBOL_GPL(divider_ro_round_rate_parent);
379427

380-
381428
static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
382429
unsigned long *prate)
383430
{

include/linux/clk-provider.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,12 @@ long divider_ro_round_rate_parent(struct clk_hw *hw, struct clk_hw *parent,
629629
unsigned long rate, unsigned long *prate,
630630
const struct clk_div_table *table, u8 width,
631631
unsigned long flags, unsigned int val);
632+
int divider_determine_rate(struct clk_hw *hw, struct clk_rate_request *req,
633+
const struct clk_div_table *table, u8 width,
634+
unsigned long flags);
635+
int divider_ro_determine_rate(struct clk_hw *hw, struct clk_rate_request *req,
636+
const struct clk_div_table *table, u8 width,
637+
unsigned long flags, unsigned int val);
632638
int divider_get_val(unsigned long rate, unsigned long parent_rate,
633639
const struct clk_div_table *table, u8 width,
634640
unsigned long flags);

0 commit comments

Comments
 (0)