Merge branch 'clk-determine-rate-struct' into clk-next
* clk-determine-rate-struct: clk: fix some determine_rate implementations clk: change clk_ops' ->determine_rate() prototype
This commit is contained in:
@@ -71,12 +71,8 @@ the operations defined in clk.h:
|
|||||||
long (*round_rate)(struct clk_hw *hw,
|
long (*round_rate)(struct clk_hw *hw,
|
||||||
unsigned long rate,
|
unsigned long rate,
|
||||||
unsigned long *parent_rate);
|
unsigned long *parent_rate);
|
||||||
long (*determine_rate)(struct clk_hw *hw,
|
int (*determine_rate)(struct clk_hw *hw,
|
||||||
unsigned long rate,
|
struct clk_rate_request *req);
|
||||||
unsigned long min_rate,
|
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_clk);
|
|
||||||
int (*set_parent)(struct clk_hw *hw, u8 index);
|
int (*set_parent)(struct clk_hw *hw, u8 index);
|
||||||
u8 (*get_parent)(struct clk_hw *hw);
|
u8 (*get_parent)(struct clk_hw *hw);
|
||||||
int (*set_rate)(struct clk_hw *hw,
|
int (*set_rate)(struct clk_hw *hw,
|
||||||
|
|||||||
@@ -462,43 +462,38 @@ void omap3_noncore_dpll_disable(struct clk_hw *hw)
|
|||||||
/**
|
/**
|
||||||
* omap3_noncore_dpll_determine_rate - determine rate for a DPLL
|
* omap3_noncore_dpll_determine_rate - determine rate for a DPLL
|
||||||
* @hw: pointer to the clock to determine rate for
|
* @hw: pointer to the clock to determine rate for
|
||||||
* @rate: target rate for the DPLL
|
* @req: target rate request
|
||||||
* @best_parent_rate: pointer for returning best parent rate
|
|
||||||
* @best_parent_clk: pointer for returning best parent clock
|
|
||||||
*
|
*
|
||||||
* Determines which DPLL mode to use for reaching a desired target rate.
|
* Determines which DPLL mode to use for reaching a desired target rate.
|
||||||
* Checks whether the DPLL shall be in bypass or locked mode, and if
|
* Checks whether the DPLL shall be in bypass or locked mode, and if
|
||||||
* locked, calculates the M,N values for the DPLL via round-rate.
|
* locked, calculates the M,N values for the DPLL via round-rate.
|
||||||
* Returns a positive clock rate with success, negative error value
|
* Returns a 0 on success, negative error value in failure.
|
||||||
* in failure.
|
|
||||||
*/
|
*/
|
||||||
long omap3_noncore_dpll_determine_rate(struct clk_hw *hw, unsigned long rate,
|
int omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_clk)
|
|
||||||
{
|
{
|
||||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||||
struct dpll_data *dd;
|
struct dpll_data *dd;
|
||||||
|
|
||||||
if (!hw || !rate)
|
if (!req->rate)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
dd = clk->dpll_data;
|
dd = clk->dpll_data;
|
||||||
if (!dd)
|
if (!dd)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (__clk_get_rate(dd->clk_bypass) == rate &&
|
if (__clk_get_rate(dd->clk_bypass) == req->rate &&
|
||||||
(dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
|
(dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
|
||||||
*best_parent_clk = __clk_get_hw(dd->clk_bypass);
|
req->best_parent_hw = __clk_get_hw(dd->clk_bypass);
|
||||||
} else {
|
} else {
|
||||||
rate = omap2_dpll_round_rate(hw, rate, best_parent_rate);
|
req->rate = omap2_dpll_round_rate(hw, req->rate,
|
||||||
*best_parent_clk = __clk_get_hw(dd->clk_ref);
|
&req->best_parent_rate);
|
||||||
|
req->best_parent_hw = __clk_get_hw(dd->clk_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
*best_parent_rate = rate;
|
req->best_parent_rate = req->rate;
|
||||||
|
|
||||||
return rate;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -191,42 +191,36 @@ out:
|
|||||||
/**
|
/**
|
||||||
* omap4_dpll_regm4xen_determine_rate - determine rate for a DPLL
|
* omap4_dpll_regm4xen_determine_rate - determine rate for a DPLL
|
||||||
* @hw: pointer to the clock to determine rate for
|
* @hw: pointer to the clock to determine rate for
|
||||||
* @rate: target rate for the DPLL
|
* @req: target rate request
|
||||||
* @best_parent_rate: pointer for returning best parent rate
|
|
||||||
* @best_parent_clk: pointer for returning best parent clock
|
|
||||||
*
|
*
|
||||||
* Determines which DPLL mode to use for reaching a desired rate.
|
* Determines which DPLL mode to use for reaching a desired rate.
|
||||||
* Checks whether the DPLL shall be in bypass or locked mode, and if
|
* Checks whether the DPLL shall be in bypass or locked mode, and if
|
||||||
* locked, calculates the M,N values for the DPLL via round-rate.
|
* locked, calculates the M,N values for the DPLL via round-rate.
|
||||||
* Returns a positive clock rate with success, negative error value
|
* Returns 0 on success and a negative error value otherwise.
|
||||||
* in failure.
|
|
||||||
*/
|
*/
|
||||||
long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw, unsigned long rate,
|
int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_clk)
|
|
||||||
{
|
{
|
||||||
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
struct clk_hw_omap *clk = to_clk_hw_omap(hw);
|
||||||
struct dpll_data *dd;
|
struct dpll_data *dd;
|
||||||
|
|
||||||
if (!hw || !rate)
|
if (!req->rate)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
dd = clk->dpll_data;
|
dd = clk->dpll_data;
|
||||||
if (!dd)
|
if (!dd)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (__clk_get_rate(dd->clk_bypass) == rate &&
|
if (__clk_get_rate(dd->clk_bypass) == req->rate &&
|
||||||
(dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
|
(dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
|
||||||
*best_parent_clk = __clk_get_hw(dd->clk_bypass);
|
req->best_parent_hw = __clk_get_hw(dd->clk_bypass);
|
||||||
} else {
|
} else {
|
||||||
rate = omap4_dpll_regm4xen_round_rate(hw, rate,
|
req->rate = omap4_dpll_regm4xen_round_rate(hw, req->rate,
|
||||||
best_parent_rate);
|
&req->best_parent_rate);
|
||||||
*best_parent_clk = __clk_get_hw(dd->clk_ref);
|
req->best_parent_hw = __clk_get_hw(dd->clk_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
*best_parent_rate = rate;
|
req->best_parent_rate = req->rate;
|
||||||
|
|
||||||
return rate;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -389,9 +389,8 @@ static long alchemy_calc_div(unsigned long rate, unsigned long prate,
|
|||||||
return div1;
|
return div1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
|
static int alchemy_clk_fgcs_detr(struct clk_hw *hw,
|
||||||
unsigned long *best_parent_rate,
|
struct clk_rate_request *req,
|
||||||
struct clk_hw **best_parent_clk,
|
|
||||||
int scale, int maxdiv)
|
int scale, int maxdiv)
|
||||||
{
|
{
|
||||||
struct clk *pc, *bpc, *free;
|
struct clk *pc, *bpc, *free;
|
||||||
@@ -422,14 +421,14 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pr = clk_get_rate(pc);
|
pr = clk_get_rate(pc);
|
||||||
if (pr < rate)
|
if (pr < req->rate)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* what can hardware actually provide */
|
/* what can hardware actually provide */
|
||||||
tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
|
tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv, NULL);
|
||||||
nr = pr / tdv;
|
nr = pr / tdv;
|
||||||
diff = rate - nr;
|
diff = req->rate - nr;
|
||||||
if (nr > rate)
|
if (nr > req->rate)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (diff < lastdiff) {
|
if (diff < lastdiff) {
|
||||||
@@ -448,15 +447,16 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
|
|||||||
*/
|
*/
|
||||||
if (lastdiff && free) {
|
if (lastdiff && free) {
|
||||||
for (j = (maxdiv == 4) ? 1 : scale; j <= maxdiv; j += scale) {
|
for (j = (maxdiv == 4) ? 1 : scale; j <= maxdiv; j += scale) {
|
||||||
tpr = rate * j;
|
tpr = req->rate * j;
|
||||||
if (tpr < 0)
|
if (tpr < 0)
|
||||||
break;
|
break;
|
||||||
pr = clk_round_rate(free, tpr);
|
pr = clk_round_rate(free, tpr);
|
||||||
|
|
||||||
tdv = alchemy_calc_div(rate, pr, scale, maxdiv, NULL);
|
tdv = alchemy_calc_div(req->rate, pr, scale, maxdiv,
|
||||||
|
NULL);
|
||||||
nr = pr / tdv;
|
nr = pr / tdv;
|
||||||
diff = rate - nr;
|
diff = req->rate - nr;
|
||||||
if (nr > rate)
|
if (nr > req->rate)
|
||||||
continue;
|
continue;
|
||||||
if (diff < lastdiff) {
|
if (diff < lastdiff) {
|
||||||
lastdiff = diff;
|
lastdiff = diff;
|
||||||
@@ -469,9 +469,14 @@ static long alchemy_clk_fgcs_detr(struct clk_hw *hw, unsigned long rate,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*best_parent_rate = bpr;
|
if (br < 0)
|
||||||
*best_parent_clk = __clk_get_hw(bpc);
|
|
||||||
return br;
|
return br;
|
||||||
|
|
||||||
|
req->best_parent_rate = bpr;
|
||||||
|
req->best_parent_hw = __clk_get_hw(bpc);
|
||||||
|
req->rate = br;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alchemy_clk_fgv1_en(struct clk_hw *hw)
|
static int alchemy_clk_fgv1_en(struct clk_hw *hw)
|
||||||
@@ -562,14 +567,10 @@ static unsigned long alchemy_clk_fgv1_recalc(struct clk_hw *hw,
|
|||||||
return parent_rate / v;
|
return parent_rate / v;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long alchemy_clk_fgv1_detr(struct clk_hw *hw, unsigned long rate,
|
static int alchemy_clk_fgv1_detr(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_clk)
|
|
||||||
{
|
{
|
||||||
return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
|
return alchemy_clk_fgcs_detr(hw, req, 2, 512);
|
||||||
best_parent_clk, 2, 512);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Au1000, Au1100, Au15x0, Au12x0 */
|
/* Au1000, Au1100, Au15x0, Au12x0 */
|
||||||
@@ -696,11 +697,8 @@ static unsigned long alchemy_clk_fgv2_recalc(struct clk_hw *hw,
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
|
static int alchemy_clk_fgv2_detr(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_clk)
|
|
||||||
{
|
{
|
||||||
struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
|
struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
|
||||||
int scale, maxdiv;
|
int scale, maxdiv;
|
||||||
@@ -713,8 +711,7 @@ static long alchemy_clk_fgv2_detr(struct clk_hw *hw, unsigned long rate,
|
|||||||
maxdiv = 512;
|
maxdiv = 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
|
return alchemy_clk_fgcs_detr(hw, req, scale, maxdiv);
|
||||||
best_parent_clk, scale, maxdiv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Au1300 larger input mux, no separate disable bit, flexible divider */
|
/* Au1300 larger input mux, no separate disable bit, flexible divider */
|
||||||
@@ -917,17 +914,13 @@ static int alchemy_clk_csrc_setr(struct clk_hw *hw, unsigned long rate,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long alchemy_clk_csrc_detr(struct clk_hw *hw, unsigned long rate,
|
static int alchemy_clk_csrc_detr(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_clk)
|
|
||||||
{
|
{
|
||||||
struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
|
struct alchemy_fgcs_clk *c = to_fgcs_clk(hw);
|
||||||
int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */
|
int scale = c->dt[2] == 3 ? 1 : 2; /* au1300 check */
|
||||||
|
|
||||||
return alchemy_clk_fgcs_detr(hw, rate, best_parent_rate,
|
return alchemy_clk_fgcs_detr(hw, req, scale, 4);
|
||||||
best_parent_clk, scale, 4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct clk_ops alchemy_clkops_csrc = {
|
static struct clk_ops alchemy_clkops_csrc = {
|
||||||
|
|||||||
@@ -54,12 +54,8 @@ static unsigned long clk_programmable_recalc_rate(struct clk_hw *hw,
|
|||||||
return parent_rate >> pres;
|
return parent_rate >> pres;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long clk_programmable_determine_rate(struct clk_hw *hw,
|
static int clk_programmable_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long min_rate,
|
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_hw)
|
|
||||||
{
|
{
|
||||||
struct clk *parent = NULL;
|
struct clk *parent = NULL;
|
||||||
long best_rate = -EINVAL;
|
long best_rate = -EINVAL;
|
||||||
@@ -76,24 +72,29 @@ static long clk_programmable_determine_rate(struct clk_hw *hw,
|
|||||||
parent_rate = __clk_get_rate(parent);
|
parent_rate = __clk_get_rate(parent);
|
||||||
for (shift = 0; shift < PROG_PRES_MASK; shift++) {
|
for (shift = 0; shift < PROG_PRES_MASK; shift++) {
|
||||||
tmp_rate = parent_rate >> shift;
|
tmp_rate = parent_rate >> shift;
|
||||||
if (tmp_rate <= rate)
|
if (tmp_rate <= req->rate)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp_rate > rate)
|
if (tmp_rate > req->rate)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (best_rate < 0 || (rate - tmp_rate) < (rate - best_rate)) {
|
if (best_rate < 0 ||
|
||||||
|
(req->rate - tmp_rate) < (req->rate - best_rate)) {
|
||||||
best_rate = tmp_rate;
|
best_rate = tmp_rate;
|
||||||
*best_parent_rate = parent_rate;
|
req->best_parent_rate = parent_rate;
|
||||||
*best_parent_hw = __clk_get_hw(parent);
|
req->best_parent_hw = __clk_get_hw(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!best_rate)
|
if (!best_rate)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (best_rate < 0)
|
||||||
return best_rate;
|
return best_rate;
|
||||||
|
|
||||||
|
req->rate = best_rate;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int clk_programmable_set_parent(struct clk_hw *hw, u8 index)
|
static int clk_programmable_set_parent(struct clk_hw *hw, u8 index)
|
||||||
|
|||||||
@@ -56,12 +56,8 @@ static unsigned long at91sam9x5_clk_usb_recalc_rate(struct clk_hw *hw,
|
|||||||
return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1));
|
return DIV_ROUND_CLOSEST(parent_rate, (usbdiv + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static long at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
|
static int at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long min_rate,
|
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_hw)
|
|
||||||
{
|
{
|
||||||
struct clk *parent = NULL;
|
struct clk *parent = NULL;
|
||||||
long best_rate = -EINVAL;
|
long best_rate = -EINVAL;
|
||||||
@@ -80,23 +76,23 @@ static long at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
|
|||||||
for (div = 1; div < SAM9X5_USB_MAX_DIV + 2; div++) {
|
for (div = 1; div < SAM9X5_USB_MAX_DIV + 2; div++) {
|
||||||
unsigned long tmp_parent_rate;
|
unsigned long tmp_parent_rate;
|
||||||
|
|
||||||
tmp_parent_rate = rate * div;
|
tmp_parent_rate = req->rate * div;
|
||||||
tmp_parent_rate = __clk_round_rate(parent,
|
tmp_parent_rate = __clk_round_rate(parent,
|
||||||
tmp_parent_rate);
|
tmp_parent_rate);
|
||||||
tmp_rate = DIV_ROUND_CLOSEST(tmp_parent_rate, div);
|
tmp_rate = DIV_ROUND_CLOSEST(tmp_parent_rate, div);
|
||||||
if (tmp_rate < rate)
|
if (tmp_rate < req->rate)
|
||||||
tmp_diff = rate - tmp_rate;
|
tmp_diff = req->rate - tmp_rate;
|
||||||
else
|
else
|
||||||
tmp_diff = tmp_rate - rate;
|
tmp_diff = tmp_rate - req->rate;
|
||||||
|
|
||||||
if (best_diff < 0 || best_diff > tmp_diff) {
|
if (best_diff < 0 || best_diff > tmp_diff) {
|
||||||
best_rate = tmp_rate;
|
best_rate = tmp_rate;
|
||||||
best_diff = tmp_diff;
|
best_diff = tmp_diff;
|
||||||
*best_parent_rate = tmp_parent_rate;
|
req->best_parent_rate = tmp_parent_rate;
|
||||||
*best_parent_hw = __clk_get_hw(parent);
|
req->best_parent_hw = __clk_get_hw(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!best_diff || tmp_rate < rate)
|
if (!best_diff || tmp_rate < req->rate)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +100,11 @@ static long at91sam9x5_clk_usb_determine_rate(struct clk_hw *hw,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (best_rate < 0)
|
||||||
return best_rate;
|
return best_rate;
|
||||||
|
|
||||||
|
req->rate = best_rate;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
|
static int at91sam9x5_clk_usb_set_parent(struct clk_hw *hw, u8 index)
|
||||||
|
|||||||
@@ -1017,10 +1017,8 @@ static long kona_peri_clk_round_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
rate ? rate : 1, *parent_rate, NULL);
|
rate ? rate : 1, *parent_rate, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int kona_peri_clk_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate, struct clk_hw **best_parent)
|
|
||||||
{
|
{
|
||||||
struct kona_clk *bcm_clk = to_kona_clk(hw);
|
struct kona_clk *bcm_clk = to_kona_clk(hw);
|
||||||
struct clk *clk = hw->clk;
|
struct clk *clk = hw->clk;
|
||||||
@@ -1029,6 +1027,7 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
unsigned long best_delta;
|
unsigned long best_delta;
|
||||||
unsigned long best_rate;
|
unsigned long best_rate;
|
||||||
u32 parent_count;
|
u32 parent_count;
|
||||||
|
long rate;
|
||||||
u32 which;
|
u32 which;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1037,14 +1036,21 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
*/
|
*/
|
||||||
WARN_ON_ONCE(bcm_clk->init_data.flags & CLK_SET_RATE_NO_REPARENT);
|
WARN_ON_ONCE(bcm_clk->init_data.flags & CLK_SET_RATE_NO_REPARENT);
|
||||||
parent_count = (u32)bcm_clk->init_data.num_parents;
|
parent_count = (u32)bcm_clk->init_data.num_parents;
|
||||||
if (parent_count < 2)
|
if (parent_count < 2) {
|
||||||
return kona_peri_clk_round_rate(hw, rate, best_parent_rate);
|
rate = kona_peri_clk_round_rate(hw, req->rate,
|
||||||
|
&req->best_parent_rate);
|
||||||
|
if (rate < 0)
|
||||||
|
return rate;
|
||||||
|
|
||||||
|
req->rate = rate;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Unless we can do better, stick with current parent */
|
/* Unless we can do better, stick with current parent */
|
||||||
current_parent = clk_get_parent(clk);
|
current_parent = clk_get_parent(clk);
|
||||||
parent_rate = __clk_get_rate(current_parent);
|
parent_rate = __clk_get_rate(current_parent);
|
||||||
best_rate = kona_peri_clk_round_rate(hw, rate, &parent_rate);
|
best_rate = kona_peri_clk_round_rate(hw, req->rate, &parent_rate);
|
||||||
best_delta = abs(best_rate - rate);
|
best_delta = abs(best_rate - req->rate);
|
||||||
|
|
||||||
/* Check whether any other parent clock can produce a better result */
|
/* Check whether any other parent clock can produce a better result */
|
||||||
for (which = 0; which < parent_count; which++) {
|
for (which = 0; which < parent_count; which++) {
|
||||||
@@ -1058,17 +1064,19 @@ static long kona_peri_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
|
|
||||||
/* We don't support CLK_SET_RATE_PARENT */
|
/* We don't support CLK_SET_RATE_PARENT */
|
||||||
parent_rate = __clk_get_rate(parent);
|
parent_rate = __clk_get_rate(parent);
|
||||||
other_rate = kona_peri_clk_round_rate(hw, rate, &parent_rate);
|
other_rate = kona_peri_clk_round_rate(hw, req->rate,
|
||||||
delta = abs(other_rate - rate);
|
&parent_rate);
|
||||||
|
delta = abs(other_rate - req->rate);
|
||||||
if (delta < best_delta) {
|
if (delta < best_delta) {
|
||||||
best_delta = delta;
|
best_delta = delta;
|
||||||
best_rate = other_rate;
|
best_rate = other_rate;
|
||||||
*best_parent = __clk_get_hw(parent);
|
req->best_parent_hw = __clk_get_hw(parent);
|
||||||
*best_parent_rate = parent_rate;
|
req->best_parent_rate = parent_rate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return best_rate;
|
req->rate = best_rate;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
|
static int kona_peri_clk_set_parent(struct clk_hw *hw, u8 index)
|
||||||
|
|||||||
@@ -55,11 +55,8 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
|
|||||||
return rate_ops->recalc_rate(rate_hw, parent_rate);
|
return rate_ops->recalc_rate(rate_hw, parent_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int clk_composite_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_p)
|
|
||||||
{
|
{
|
||||||
struct clk_composite *composite = to_clk_composite(hw);
|
struct clk_composite *composite = to_clk_composite(hw);
|
||||||
const struct clk_ops *rate_ops = composite->rate_ops;
|
const struct clk_ops *rate_ops = composite->rate_ops;
|
||||||
@@ -71,25 +68,28 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
long tmp_rate, best_rate = 0;
|
long tmp_rate, best_rate = 0;
|
||||||
unsigned long rate_diff;
|
unsigned long rate_diff;
|
||||||
unsigned long best_rate_diff = ULONG_MAX;
|
unsigned long best_rate_diff = ULONG_MAX;
|
||||||
|
long rate;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (rate_hw && rate_ops && rate_ops->determine_rate) {
|
if (rate_hw && rate_ops && rate_ops->determine_rate) {
|
||||||
__clk_hw_set_clk(rate_hw, hw);
|
__clk_hw_set_clk(rate_hw, hw);
|
||||||
return rate_ops->determine_rate(rate_hw, rate, min_rate,
|
return rate_ops->determine_rate(rate_hw, req);
|
||||||
max_rate,
|
|
||||||
best_parent_rate,
|
|
||||||
best_parent_p);
|
|
||||||
} else if (rate_hw && rate_ops && rate_ops->round_rate &&
|
} else if (rate_hw && rate_ops && rate_ops->round_rate &&
|
||||||
mux_hw && mux_ops && mux_ops->set_parent) {
|
mux_hw && mux_ops && mux_ops->set_parent) {
|
||||||
*best_parent_p = NULL;
|
req->best_parent_hw = NULL;
|
||||||
|
|
||||||
if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) {
|
if (__clk_get_flags(hw->clk) & CLK_SET_RATE_NO_REPARENT) {
|
||||||
parent = clk_get_parent(mux_hw->clk);
|
parent = clk_get_parent(mux_hw->clk);
|
||||||
*best_parent_p = __clk_get_hw(parent);
|
req->best_parent_hw = __clk_get_hw(parent);
|
||||||
*best_parent_rate = __clk_get_rate(parent);
|
req->best_parent_rate = __clk_get_rate(parent);
|
||||||
|
|
||||||
return rate_ops->round_rate(rate_hw, rate,
|
rate = rate_ops->round_rate(rate_hw, req->rate,
|
||||||
best_parent_rate);
|
&req->best_parent_rate);
|
||||||
|
if (rate < 0)
|
||||||
|
return rate;
|
||||||
|
|
||||||
|
req->rate = rate;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) {
|
for (i = 0; i < __clk_get_num_parents(mux_hw->clk); i++) {
|
||||||
@@ -99,34 +99,33 @@ static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
|
|
||||||
parent_rate = __clk_get_rate(parent);
|
parent_rate = __clk_get_rate(parent);
|
||||||
|
|
||||||
tmp_rate = rate_ops->round_rate(rate_hw, rate,
|
tmp_rate = rate_ops->round_rate(rate_hw, req->rate,
|
||||||
&parent_rate);
|
&parent_rate);
|
||||||
if (tmp_rate < 0)
|
if (tmp_rate < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
rate_diff = abs(rate - tmp_rate);
|
rate_diff = abs(req->rate - tmp_rate);
|
||||||
|
|
||||||
if (!rate_diff || !*best_parent_p
|
if (!rate_diff || !req->best_parent_hw
|
||||||
|| best_rate_diff > rate_diff) {
|
|| best_rate_diff > rate_diff) {
|
||||||
*best_parent_p = __clk_get_hw(parent);
|
req->best_parent_hw = __clk_get_hw(parent);
|
||||||
*best_parent_rate = parent_rate;
|
req->best_parent_rate = parent_rate;
|
||||||
best_rate_diff = rate_diff;
|
best_rate_diff = rate_diff;
|
||||||
best_rate = tmp_rate;
|
best_rate = tmp_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rate_diff)
|
if (!rate_diff)
|
||||||
return rate;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return best_rate;
|
req->rate = best_rate;
|
||||||
|
return 0;
|
||||||
} else if (mux_hw && mux_ops && mux_ops->determine_rate) {
|
} else if (mux_hw && mux_ops && mux_ops->determine_rate) {
|
||||||
__clk_hw_set_clk(mux_hw, hw);
|
__clk_hw_set_clk(mux_hw, hw);
|
||||||
return mux_ops->determine_rate(mux_hw, rate, min_rate,
|
return mux_ops->determine_rate(mux_hw, req);
|
||||||
max_rate, best_parent_rate,
|
|
||||||
best_parent_p);
|
|
||||||
} else {
|
} else {
|
||||||
pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
|
pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
|
||||||
return 0;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -436,28 +436,31 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now,
|
|||||||
return now <= rate && now > best;
|
return now <= rate && now > best;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long
|
static int
|
||||||
clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate,
|
clk_mux_determine_rate_flags(struct clk_hw *hw, struct clk_rate_request *req,
|
||||||
unsigned long min_rate,
|
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_p,
|
|
||||||
unsigned long flags)
|
unsigned long flags)
|
||||||
{
|
{
|
||||||
struct clk_core *core = hw->core, *parent, *best_parent = NULL;
|
struct clk_core *core = hw->core, *parent, *best_parent = NULL;
|
||||||
int i, num_parents;
|
int i, num_parents, ret;
|
||||||
unsigned long parent_rate, best = 0;
|
unsigned long best = 0;
|
||||||
|
struct clk_rate_request parent_req = *req;
|
||||||
|
|
||||||
/* if NO_REPARENT flag set, pass through to current parent */
|
/* if NO_REPARENT flag set, pass through to current parent */
|
||||||
if (core->flags & CLK_SET_RATE_NO_REPARENT) {
|
if (core->flags & CLK_SET_RATE_NO_REPARENT) {
|
||||||
parent = core->parent;
|
parent = core->parent;
|
||||||
if (core->flags & CLK_SET_RATE_PARENT)
|
if (core->flags & CLK_SET_RATE_PARENT) {
|
||||||
best = __clk_determine_rate(parent ? parent->hw : NULL,
|
ret = __clk_determine_rate(parent ? parent->hw : NULL,
|
||||||
rate, min_rate, max_rate);
|
&parent_req);
|
||||||
else if (parent)
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
best = parent_req.rate;
|
||||||
|
} else if (parent) {
|
||||||
best = clk_core_get_rate_nolock(parent);
|
best = clk_core_get_rate_nolock(parent);
|
||||||
else
|
} else {
|
||||||
best = clk_core_get_rate_nolock(core);
|
best = clk_core_get_rate_nolock(core);
|
||||||
|
}
|
||||||
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,24 +470,33 @@ clk_mux_determine_rate_flags(struct clk_hw *hw, unsigned long rate,
|
|||||||
parent = clk_core_get_parent_by_index(core, i);
|
parent = clk_core_get_parent_by_index(core, i);
|
||||||
if (!parent)
|
if (!parent)
|
||||||
continue;
|
continue;
|
||||||
if (core->flags & CLK_SET_RATE_PARENT)
|
|
||||||
parent_rate = __clk_determine_rate(parent->hw, rate,
|
if (core->flags & CLK_SET_RATE_PARENT) {
|
||||||
min_rate,
|
parent_req = *req;
|
||||||
max_rate);
|
ret = __clk_determine_rate(parent->hw, &parent_req);
|
||||||
else
|
if (ret)
|
||||||
parent_rate = clk_core_get_rate_nolock(parent);
|
continue;
|
||||||
if (mux_is_better_rate(rate, parent_rate, best, flags)) {
|
} else {
|
||||||
|
parent_req.rate = clk_core_get_rate_nolock(parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mux_is_better_rate(req->rate, parent_req.rate,
|
||||||
|
best, flags)) {
|
||||||
best_parent = parent;
|
best_parent = parent;
|
||||||
best = parent_rate;
|
best = parent_req.rate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!best_parent)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (best_parent)
|
if (best_parent)
|
||||||
*best_parent_p = best_parent->hw;
|
req->best_parent_hw = best_parent->hw;
|
||||||
*best_parent_rate = best;
|
req->best_parent_rate = best;
|
||||||
|
req->rate = best;
|
||||||
|
|
||||||
return best;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct clk *__clk_lookup(const char *name)
|
struct clk *__clk_lookup(const char *name)
|
||||||
@@ -515,28 +527,17 @@ static void clk_core_get_boundaries(struct clk_core *core,
|
|||||||
* directly as a determine_rate callback (e.g. for a mux), or from a more
|
* directly as a determine_rate callback (e.g. for a mux), or from a more
|
||||||
* complex clock that may combine a mux with other operations.
|
* complex clock that may combine a mux with other operations.
|
||||||
*/
|
*/
|
||||||
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
|
int __clk_mux_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_p)
|
|
||||||
{
|
{
|
||||||
return clk_mux_determine_rate_flags(hw, rate, min_rate, max_rate,
|
return clk_mux_determine_rate_flags(hw, req, 0);
|
||||||
best_parent_rate,
|
|
||||||
best_parent_p, 0);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
|
EXPORT_SYMBOL_GPL(__clk_mux_determine_rate);
|
||||||
|
|
||||||
long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
|
int __clk_mux_determine_rate_closest(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_p)
|
|
||||||
{
|
{
|
||||||
return clk_mux_determine_rate_flags(hw, rate, min_rate, max_rate,
|
return clk_mux_determine_rate_flags(hw, req, CLK_MUX_ROUND_CLOSEST);
|
||||||
best_parent_rate,
|
|
||||||
best_parent_p,
|
|
||||||
CLK_MUX_ROUND_CLOSEST);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest);
|
EXPORT_SYMBOL_GPL(__clk_mux_determine_rate_closest);
|
||||||
|
|
||||||
@@ -759,14 +760,11 @@ int clk_enable(struct clk *clk)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(clk_enable);
|
EXPORT_SYMBOL_GPL(clk_enable);
|
||||||
|
|
||||||
static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
|
static int clk_core_round_rate_nolock(struct clk_core *core,
|
||||||
unsigned long rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long min_rate,
|
|
||||||
unsigned long max_rate)
|
|
||||||
{
|
{
|
||||||
unsigned long parent_rate = 0;
|
|
||||||
struct clk_core *parent;
|
struct clk_core *parent;
|
||||||
struct clk_hw *parent_hw;
|
long rate;
|
||||||
|
|
||||||
lockdep_assert_held(&prepare_lock);
|
lockdep_assert_held(&prepare_lock);
|
||||||
|
|
||||||
@@ -774,21 +772,30 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
parent = core->parent;
|
parent = core->parent;
|
||||||
if (parent)
|
if (parent) {
|
||||||
parent_rate = parent->rate;
|
req->best_parent_hw = parent->hw;
|
||||||
|
req->best_parent_rate = parent->rate;
|
||||||
|
} else {
|
||||||
|
req->best_parent_hw = NULL;
|
||||||
|
req->best_parent_rate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (core->ops->determine_rate) {
|
if (core->ops->determine_rate) {
|
||||||
parent_hw = parent ? parent->hw : NULL;
|
return core->ops->determine_rate(core->hw, req);
|
||||||
return core->ops->determine_rate(core->hw, rate,
|
} else if (core->ops->round_rate) {
|
||||||
min_rate, max_rate,
|
rate = core->ops->round_rate(core->hw, req->rate,
|
||||||
&parent_rate, &parent_hw);
|
&req->best_parent_rate);
|
||||||
} else if (core->ops->round_rate)
|
if (rate < 0)
|
||||||
return core->ops->round_rate(core->hw, rate, &parent_rate);
|
return rate;
|
||||||
else if (core->flags & CLK_SET_RATE_PARENT)
|
|
||||||
return clk_core_round_rate_nolock(core->parent, rate, min_rate,
|
req->rate = rate;
|
||||||
max_rate);
|
} else if (core->flags & CLK_SET_RATE_PARENT) {
|
||||||
else
|
return clk_core_round_rate_nolock(parent, req);
|
||||||
return core->rate;
|
} else {
|
||||||
|
req->rate = core->rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -800,15 +807,14 @@ static unsigned long clk_core_round_rate_nolock(struct clk_core *core,
|
|||||||
*
|
*
|
||||||
* Useful for clk_ops such as .set_rate and .determine_rate.
|
* Useful for clk_ops such as .set_rate and .determine_rate.
|
||||||
*/
|
*/
|
||||||
unsigned long __clk_determine_rate(struct clk_hw *hw,
|
int __clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
|
||||||
unsigned long rate,
|
|
||||||
unsigned long min_rate,
|
|
||||||
unsigned long max_rate)
|
|
||||||
{
|
{
|
||||||
if (!hw)
|
if (!hw) {
|
||||||
|
req->rate = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return clk_core_round_rate_nolock(hw->core, rate, min_rate, max_rate);
|
return clk_core_round_rate_nolock(hw->core, req);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__clk_determine_rate);
|
EXPORT_SYMBOL_GPL(__clk_determine_rate);
|
||||||
|
|
||||||
@@ -821,15 +827,20 @@ EXPORT_SYMBOL_GPL(__clk_determine_rate);
|
|||||||
*/
|
*/
|
||||||
unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
|
unsigned long __clk_round_rate(struct clk *clk, unsigned long rate)
|
||||||
{
|
{
|
||||||
unsigned long min_rate;
|
struct clk_rate_request req;
|
||||||
unsigned long max_rate;
|
int ret;
|
||||||
|
|
||||||
if (!clk)
|
if (!clk)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
clk_core_get_boundaries(clk->core, &min_rate, &max_rate);
|
clk_core_get_boundaries(clk->core, &req.min_rate, &req.max_rate);
|
||||||
|
req.rate = rate;
|
||||||
|
|
||||||
return clk_core_round_rate_nolock(clk->core, rate, min_rate, max_rate);
|
ret = clk_core_round_rate_nolock(clk->core, &req);
|
||||||
|
if (ret)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return req.rate;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(__clk_round_rate);
|
EXPORT_SYMBOL_GPL(__clk_round_rate);
|
||||||
|
|
||||||
@@ -1249,7 +1260,6 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
|
|||||||
{
|
{
|
||||||
struct clk_core *top = core;
|
struct clk_core *top = core;
|
||||||
struct clk_core *old_parent, *parent;
|
struct clk_core *old_parent, *parent;
|
||||||
struct clk_hw *parent_hw;
|
|
||||||
unsigned long best_parent_rate = 0;
|
unsigned long best_parent_rate = 0;
|
||||||
unsigned long new_rate;
|
unsigned long new_rate;
|
||||||
unsigned long min_rate;
|
unsigned long min_rate;
|
||||||
@@ -1270,17 +1280,26 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
|
|||||||
|
|
||||||
/* find the closest rate and parent clk/rate */
|
/* find the closest rate and parent clk/rate */
|
||||||
if (core->ops->determine_rate) {
|
if (core->ops->determine_rate) {
|
||||||
parent_hw = parent ? parent->hw : NULL;
|
struct clk_rate_request req;
|
||||||
ret = core->ops->determine_rate(core->hw, rate,
|
|
||||||
min_rate,
|
req.rate = rate;
|
||||||
max_rate,
|
req.min_rate = min_rate;
|
||||||
&best_parent_rate,
|
req.max_rate = max_rate;
|
||||||
&parent_hw);
|
if (parent) {
|
||||||
|
req.best_parent_hw = parent->hw;
|
||||||
|
req.best_parent_rate = parent->rate;
|
||||||
|
} else {
|
||||||
|
req.best_parent_hw = NULL;
|
||||||
|
req.best_parent_rate = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = core->ops->determine_rate(core->hw, &req);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
new_rate = ret;
|
best_parent_rate = req.best_parent_rate;
|
||||||
parent = parent_hw ? parent_hw->core : NULL;
|
new_rate = req.rate;
|
||||||
|
parent = req.best_parent_hw ? req.best_parent_hw->core : NULL;
|
||||||
} else if (core->ops->round_rate) {
|
} else if (core->ops->round_rate) {
|
||||||
ret = core->ops->round_rate(core->hw, rate,
|
ret = core->ops->round_rate(core->hw, rate,
|
||||||
&best_parent_rate);
|
&best_parent_rate);
|
||||||
|
|||||||
@@ -294,34 +294,29 @@ static unsigned long mmc_clk_recalc_rate(struct clk_hw *hw,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static long mmc_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int mmc_clk_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_p)
|
|
||||||
{
|
{
|
||||||
struct clk_mmc *mclk = to_mmc(hw);
|
struct clk_mmc *mclk = to_mmc(hw);
|
||||||
unsigned long best = 0;
|
|
||||||
|
|
||||||
if ((rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
|
if ((req->rate <= 13000000) && (mclk->id == HI3620_MMC_CIUCLK1)) {
|
||||||
rate = 13000000;
|
req->rate = 13000000;
|
||||||
best = 26000000;
|
req->best_parent_rate = 26000000;
|
||||||
} else if (rate <= 26000000) {
|
} else if (req->rate <= 26000000) {
|
||||||
rate = 25000000;
|
req->rate = 25000000;
|
||||||
best = 180000000;
|
req->best_parent_rate = 180000000;
|
||||||
} else if (rate <= 52000000) {
|
} else if (req->rate <= 52000000) {
|
||||||
rate = 50000000;
|
req->rate = 50000000;
|
||||||
best = 360000000;
|
req->best_parent_rate = 360000000;
|
||||||
} else if (rate <= 100000000) {
|
} else if (req->rate <= 100000000) {
|
||||||
rate = 100000000;
|
req->rate = 100000000;
|
||||||
best = 720000000;
|
req->best_parent_rate = 720000000;
|
||||||
} else {
|
} else {
|
||||||
/* max is 180M */
|
/* max is 180M */
|
||||||
rate = 180000000;
|
req->rate = 180000000;
|
||||||
best = 1440000000;
|
req->best_parent_rate = 1440000000;
|
||||||
}
|
}
|
||||||
*best_parent_rate = best;
|
return -EINVAL;
|
||||||
return rate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
|
static u32 mmc_clk_delay(u32 val, u32 para, u32 off, u32 len)
|
||||||
|
|||||||
@@ -201,11 +201,8 @@ error:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int mmp_clk_mix_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_clk)
|
|
||||||
{
|
{
|
||||||
struct mmp_clk_mix *mix = to_clk_mix(hw);
|
struct mmp_clk_mix *mix = to_clk_mix(hw);
|
||||||
struct mmp_clk_mix_clk_table *item;
|
struct mmp_clk_mix_clk_table *item;
|
||||||
@@ -221,7 +218,7 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
parent = NULL;
|
parent = NULL;
|
||||||
mix_rate_best = 0;
|
mix_rate_best = 0;
|
||||||
parent_rate_best = 0;
|
parent_rate_best = 0;
|
||||||
gap_best = rate;
|
gap_best = ULONG_MAX;
|
||||||
parent_best = NULL;
|
parent_best = NULL;
|
||||||
|
|
||||||
if (mix->table) {
|
if (mix->table) {
|
||||||
@@ -233,7 +230,7 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
item->parent_index);
|
item->parent_index);
|
||||||
parent_rate = __clk_get_rate(parent);
|
parent_rate = __clk_get_rate(parent);
|
||||||
mix_rate = parent_rate / item->divisor;
|
mix_rate = parent_rate / item->divisor;
|
||||||
gap = abs(mix_rate - rate);
|
gap = abs(mix_rate - req->rate);
|
||||||
if (parent_best == NULL || gap < gap_best) {
|
if (parent_best == NULL || gap < gap_best) {
|
||||||
parent_best = parent;
|
parent_best = parent;
|
||||||
parent_rate_best = parent_rate;
|
parent_rate_best = parent_rate;
|
||||||
@@ -251,7 +248,7 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
for (j = 0; j < div_val_max; j++) {
|
for (j = 0; j < div_val_max; j++) {
|
||||||
div = _get_div(mix, j);
|
div = _get_div(mix, j);
|
||||||
mix_rate = parent_rate / div;
|
mix_rate = parent_rate / div;
|
||||||
gap = abs(mix_rate - rate);
|
gap = abs(mix_rate - req->rate);
|
||||||
if (parent_best == NULL || gap < gap_best) {
|
if (parent_best == NULL || gap < gap_best) {
|
||||||
parent_best = parent;
|
parent_best = parent;
|
||||||
parent_rate_best = parent_rate;
|
parent_rate_best = parent_rate;
|
||||||
@@ -265,10 +262,14 @@ static long mmp_clk_mix_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
}
|
}
|
||||||
|
|
||||||
found:
|
found:
|
||||||
*best_parent_rate = parent_rate_best;
|
if (!parent_best)
|
||||||
*best_parent_clk = __clk_get_hw(parent_best);
|
return -EINVAL;
|
||||||
|
|
||||||
return mix_rate_best;
|
req->best_parent_rate = parent_rate_best;
|
||||||
|
req->best_parent_hw = __clk_get_hw(parent_best);
|
||||||
|
req->rate = mix_rate_best;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mmp_clk_mix_set_rate_and_parent(struct clk_hw *hw,
|
static int mmp_clk_mix_set_rate_and_parent(struct clk_hw *hw,
|
||||||
|
|||||||
@@ -135,19 +135,23 @@ struct pll_freq_tbl *find_freq(const struct pll_freq_tbl *f, unsigned long rate)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long
|
static int
|
||||||
clk_pll_determine_rate(struct clk_hw *hw, unsigned long rate,
|
clk_pll_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
|
||||||
unsigned long min_rate, unsigned long max_rate,
|
|
||||||
unsigned long *p_rate, struct clk_hw **p)
|
|
||||||
{
|
{
|
||||||
|
struct clk *parent = __clk_get_parent(hw->clk);
|
||||||
struct clk_pll *pll = to_clk_pll(hw);
|
struct clk_pll *pll = to_clk_pll(hw);
|
||||||
const struct pll_freq_tbl *f;
|
const struct pll_freq_tbl *f;
|
||||||
|
|
||||||
f = find_freq(pll->freq_tbl, rate);
|
req->best_parent_hw = __clk_get_hw(parent);
|
||||||
if (!f)
|
req->best_parent_rate = __clk_get_rate(parent);
|
||||||
return clk_pll_recalc_rate(hw, *p_rate);
|
|
||||||
|
|
||||||
return f->freq;
|
f = find_freq(pll->freq_tbl, req->rate);
|
||||||
|
if (!f)
|
||||||
|
req->rate = clk_pll_recalc_rate(hw, req->best_parent_rate);
|
||||||
|
else
|
||||||
|
req->rate = f->freq;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|||||||
@@ -404,13 +404,11 @@ clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
|||||||
return calc_rate(parent_rate, m, n, mode, pre_div);
|
return calc_rate(parent_rate, m, n, mode, pre_div);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long _freq_tbl_determine_rate(struct clk_hw *hw,
|
static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f,
|
||||||
const struct freq_tbl *f, unsigned long rate,
|
struct clk_rate_request *req,
|
||||||
unsigned long min_rate, unsigned long max_rate,
|
|
||||||
unsigned long *p_rate, struct clk_hw **p_hw,
|
|
||||||
const struct parent_map *parent_map)
|
const struct parent_map *parent_map)
|
||||||
{
|
{
|
||||||
unsigned long clk_flags;
|
unsigned long clk_flags, rate = req->rate;
|
||||||
struct clk *p;
|
struct clk *p;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
@@ -435,25 +433,24 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
|
|||||||
} else {
|
} else {
|
||||||
rate = __clk_get_rate(p);
|
rate = __clk_get_rate(p);
|
||||||
}
|
}
|
||||||
*p_hw = __clk_get_hw(p);
|
req->best_parent_hw = __clk_get_hw(p);
|
||||||
*p_rate = rate;
|
req->best_parent_rate = rate;
|
||||||
|
req->rate = f->freq;
|
||||||
|
|
||||||
return f->freq;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int clk_rcg_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate, unsigned long max_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long *p_rate, struct clk_hw **p)
|
|
||||||
{
|
{
|
||||||
struct clk_rcg *rcg = to_clk_rcg(hw);
|
struct clk_rcg *rcg = to_clk_rcg(hw);
|
||||||
|
|
||||||
return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
|
return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req,
|
||||||
max_rate, p_rate, p, rcg->s.parent_map);
|
rcg->s.parent_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int clk_dyn_rcg_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate, unsigned long max_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long *p_rate, struct clk_hw **p)
|
|
||||||
{
|
{
|
||||||
struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
|
struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
|
||||||
u32 reg;
|
u32 reg;
|
||||||
@@ -464,13 +461,11 @@ static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
bank = reg_to_bank(rcg, reg);
|
bank = reg_to_bank(rcg, reg);
|
||||||
s = &rcg->s[bank];
|
s = &rcg->s[bank];
|
||||||
|
|
||||||
return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, min_rate,
|
return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, s->parent_map);
|
||||||
max_rate, p_rate, p, s->parent_map);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int clk_rcg_bypass_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate, unsigned long max_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long *p_rate, struct clk_hw **p_hw)
|
|
||||||
{
|
{
|
||||||
struct clk_rcg *rcg = to_clk_rcg(hw);
|
struct clk_rcg *rcg = to_clk_rcg(hw);
|
||||||
const struct freq_tbl *f = rcg->freq_tbl;
|
const struct freq_tbl *f = rcg->freq_tbl;
|
||||||
@@ -478,10 +473,11 @@ static long clk_rcg_bypass_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
int index = qcom_find_src_index(hw, rcg->s.parent_map, f->src);
|
int index = qcom_find_src_index(hw, rcg->s.parent_map, f->src);
|
||||||
|
|
||||||
p = clk_get_parent_by_index(hw->clk, index);
|
p = clk_get_parent_by_index(hw->clk, index);
|
||||||
*p_hw = __clk_get_hw(p);
|
req->best_parent_hw = __clk_get_hw(p);
|
||||||
*p_rate = __clk_round_rate(p, rate);
|
req->best_parent_rate = __clk_round_rate(p, req->rate);
|
||||||
|
req->rate = req->best_parent_rate;
|
||||||
|
|
||||||
return *p_rate;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __clk_rcg_set_rate(struct clk_rcg *rcg, const struct freq_tbl *f)
|
static int __clk_rcg_set_rate(struct clk_rcg *rcg, const struct freq_tbl *f)
|
||||||
|
|||||||
@@ -176,11 +176,10 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
|||||||
return calc_rate(parent_rate, m, n, mode, hid_div);
|
return calc_rate(parent_rate, m, n, mode, hid_div);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long _freq_tbl_determine_rate(struct clk_hw *hw,
|
static int _freq_tbl_determine_rate(struct clk_hw *hw,
|
||||||
const struct freq_tbl *f, unsigned long rate,
|
const struct freq_tbl *f, struct clk_rate_request *req)
|
||||||
unsigned long *p_rate, struct clk_hw **p_hw)
|
|
||||||
{
|
{
|
||||||
unsigned long clk_flags;
|
unsigned long clk_flags, rate = req->rate;
|
||||||
struct clk *p;
|
struct clk *p;
|
||||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||||
int index;
|
int index;
|
||||||
@@ -210,19 +209,19 @@ static long _freq_tbl_determine_rate(struct clk_hw *hw,
|
|||||||
} else {
|
} else {
|
||||||
rate = __clk_get_rate(p);
|
rate = __clk_get_rate(p);
|
||||||
}
|
}
|
||||||
*p_hw = __clk_get_hw(p);
|
req->best_parent_hw = __clk_get_hw(p);
|
||||||
*p_rate = rate;
|
req->best_parent_rate = rate;
|
||||||
|
req->rate = f->freq;
|
||||||
|
|
||||||
return f->freq;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int clk_rcg2_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate, unsigned long max_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long *p_rate, struct clk_hw **p)
|
|
||||||
{
|
{
|
||||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||||
|
|
||||||
return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
|
return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
|
static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
|
||||||
@@ -374,35 +373,34 @@ static int clk_edp_pixel_set_rate_and_parent(struct clk_hw *hw,
|
|||||||
return clk_edp_pixel_set_rate(hw, rate, parent_rate);
|
return clk_edp_pixel_set_rate(hw, rate, parent_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int clk_edp_pixel_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *p_rate, struct clk_hw **p)
|
|
||||||
{
|
{
|
||||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||||
const struct freq_tbl *f = rcg->freq_tbl;
|
const struct freq_tbl *f = rcg->freq_tbl;
|
||||||
const struct frac_entry *frac;
|
const struct frac_entry *frac;
|
||||||
int delta = 100000;
|
int delta = 100000;
|
||||||
s64 src_rate = *p_rate;
|
|
||||||
s64 request;
|
s64 request;
|
||||||
u32 mask = BIT(rcg->hid_width) - 1;
|
u32 mask = BIT(rcg->hid_width) - 1;
|
||||||
u32 hid_div;
|
u32 hid_div;
|
||||||
int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
|
int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
|
||||||
|
struct clk *p = clk_get_parent_by_index(hw->clk, index);
|
||||||
|
|
||||||
/* Force the correct parent */
|
/* Force the correct parent */
|
||||||
*p = __clk_get_hw(clk_get_parent_by_index(hw->clk, index));
|
req->best_parent_hw = __clk_get_hw(p);
|
||||||
|
req->best_parent_rate = __clk_get_rate(p);
|
||||||
|
|
||||||
if (src_rate == 810000000)
|
if (req->best_parent_rate == 810000000)
|
||||||
frac = frac_table_810m;
|
frac = frac_table_810m;
|
||||||
else
|
else
|
||||||
frac = frac_table_675m;
|
frac = frac_table_675m;
|
||||||
|
|
||||||
for (; frac->num; frac++) {
|
for (; frac->num; frac++) {
|
||||||
request = rate;
|
request = req->rate;
|
||||||
request *= frac->den;
|
request *= frac->den;
|
||||||
request = div_s64(request, frac->num);
|
request = div_s64(request, frac->num);
|
||||||
if ((src_rate < (request - delta)) ||
|
if ((req->best_parent_rate < (request - delta)) ||
|
||||||
(src_rate > (request + delta)))
|
(req->best_parent_rate > (request + delta)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
|
regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
|
||||||
@@ -410,8 +408,10 @@ static long clk_edp_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
hid_div >>= CFG_SRC_DIV_SHIFT;
|
hid_div >>= CFG_SRC_DIV_SHIFT;
|
||||||
hid_div &= mask;
|
hid_div &= mask;
|
||||||
|
|
||||||
return calc_rate(src_rate, frac->num, frac->den, !!frac->den,
|
req->rate = calc_rate(req->best_parent_rate,
|
||||||
hid_div);
|
frac->num, frac->den,
|
||||||
|
!!frac->den, hid_div);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -428,9 +428,8 @@ const struct clk_ops clk_edp_pixel_ops = {
|
|||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(clk_edp_pixel_ops);
|
EXPORT_SYMBOL_GPL(clk_edp_pixel_ops);
|
||||||
|
|
||||||
static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int clk_byte_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate, unsigned long max_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long *p_rate, struct clk_hw **p_hw)
|
|
||||||
{
|
{
|
||||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||||
const struct freq_tbl *f = rcg->freq_tbl;
|
const struct freq_tbl *f = rcg->freq_tbl;
|
||||||
@@ -439,17 +438,19 @@ static long clk_byte_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
u32 mask = BIT(rcg->hid_width) - 1;
|
u32 mask = BIT(rcg->hid_width) - 1;
|
||||||
struct clk *p;
|
struct clk *p;
|
||||||
|
|
||||||
if (rate == 0)
|
if (req->rate == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
p = clk_get_parent_by_index(hw->clk, index);
|
p = clk_get_parent_by_index(hw->clk, index);
|
||||||
*p_hw = __clk_get_hw(p);
|
req->best_parent_hw = __clk_get_hw(p);
|
||||||
*p_rate = parent_rate = __clk_round_rate(p, rate);
|
req->best_parent_rate = parent_rate = __clk_round_rate(p, req->rate);
|
||||||
|
|
||||||
div = DIV_ROUND_UP((2 * parent_rate), rate) - 1;
|
div = DIV_ROUND_UP((2 * parent_rate), req->rate) - 1;
|
||||||
div = min_t(u32, div, mask);
|
div = min_t(u32, div, mask);
|
||||||
|
|
||||||
return calc_rate(parent_rate, 0, 0, 0, div);
|
req->rate = calc_rate(parent_rate, 0, 0, 0, div);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int clk_byte_set_rate(struct clk_hw *hw, unsigned long rate,
|
static int clk_byte_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
@@ -494,10 +495,8 @@ static const struct frac_entry frac_table_pixel[] = {
|
|||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int clk_pixel_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *p_rate, struct clk_hw **p)
|
|
||||||
{
|
{
|
||||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||||
unsigned long request, src_rate;
|
unsigned long request, src_rate;
|
||||||
@@ -507,18 +506,19 @@ static long clk_pixel_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
|
int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
|
||||||
struct clk *parent = clk_get_parent_by_index(hw->clk, index);
|
struct clk *parent = clk_get_parent_by_index(hw->clk, index);
|
||||||
|
|
||||||
*p = __clk_get_hw(parent);
|
req->best_parent_hw = __clk_get_hw(parent);
|
||||||
|
|
||||||
for (; frac->num; frac++) {
|
for (; frac->num; frac++) {
|
||||||
request = (rate * frac->den) / frac->num;
|
request = (req->rate * frac->den) / frac->num;
|
||||||
|
|
||||||
src_rate = __clk_round_rate(parent, request);
|
src_rate = __clk_round_rate(parent, request);
|
||||||
if ((src_rate < (request - delta)) ||
|
if ((src_rate < (request - delta)) ||
|
||||||
(src_rate > (request + delta)))
|
(src_rate > (request + delta)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
*p_rate = src_rate;
|
req->best_parent_rate = src_rate;
|
||||||
return (src_rate * frac->num) / frac->den;
|
req->rate = (src_rate * frac->num) / frac->den;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|||||||
@@ -79,11 +79,8 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
return rate;
|
return rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int clk_factors_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_p)
|
|
||||||
{
|
{
|
||||||
struct clk *clk = hw->clk, *parent, *best_parent = NULL;
|
struct clk *clk = hw->clk, *parent, *best_parent = NULL;
|
||||||
int i, num_parents;
|
int i, num_parents;
|
||||||
@@ -96,24 +93,28 @@ static long clk_factors_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
if (!parent)
|
if (!parent)
|
||||||
continue;
|
continue;
|
||||||
if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
|
if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
|
||||||
parent_rate = __clk_round_rate(parent, rate);
|
parent_rate = __clk_round_rate(parent, req->rate);
|
||||||
else
|
else
|
||||||
parent_rate = __clk_get_rate(parent);
|
parent_rate = __clk_get_rate(parent);
|
||||||
|
|
||||||
child_rate = clk_factors_round_rate(hw, rate, &parent_rate);
|
child_rate = clk_factors_round_rate(hw, req->rate,
|
||||||
|
&parent_rate);
|
||||||
|
|
||||||
if (child_rate <= rate && child_rate > best_child_rate) {
|
if (child_rate <= req->rate && child_rate > best_child_rate) {
|
||||||
best_parent = parent;
|
best_parent = parent;
|
||||||
best = parent_rate;
|
best = parent_rate;
|
||||||
best_child_rate = child_rate;
|
best_child_rate = child_rate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (best_parent)
|
if (!best_parent)
|
||||||
*best_parent_p = __clk_get_hw(best_parent);
|
return -EINVAL;
|
||||||
*best_parent_rate = best;
|
|
||||||
|
|
||||||
return best_child_rate;
|
req->best_parent_hw = __clk_get_hw(best_parent);
|
||||||
|
req->best_parent_rate = best;
|
||||||
|
req->rate = best_child_rate;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
|
static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
|||||||
@@ -44,17 +44,14 @@ static unsigned long ar100_recalc_rate(struct clk_hw *hw,
|
|||||||
return (parent_rate >> shift) / (div + 1);
|
return (parent_rate >> shift) / (div + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int ar100_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_clk)
|
|
||||||
{
|
{
|
||||||
int nparents = __clk_get_num_parents(hw->clk);
|
int nparents = __clk_get_num_parents(hw->clk);
|
||||||
long best_rate = -EINVAL;
|
long best_rate = -EINVAL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
*best_parent_clk = NULL;
|
req->best_parent_hw = NULL;
|
||||||
|
|
||||||
for (i = 0; i < nparents; i++) {
|
for (i = 0; i < nparents; i++) {
|
||||||
unsigned long parent_rate;
|
unsigned long parent_rate;
|
||||||
@@ -65,7 +62,7 @@ static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
|
|
||||||
parent = clk_get_parent_by_index(hw->clk, i);
|
parent = clk_get_parent_by_index(hw->clk, i);
|
||||||
parent_rate = __clk_get_rate(parent);
|
parent_rate = __clk_get_rate(parent);
|
||||||
div = DIV_ROUND_UP(parent_rate, rate);
|
div = DIV_ROUND_UP(parent_rate, req->rate);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The AR100 clk contains 2 divisors:
|
* The AR100 clk contains 2 divisors:
|
||||||
@@ -101,14 +98,19 @@ static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
tmp_rate = (parent_rate >> shift) / div;
|
tmp_rate = (parent_rate >> shift) / div;
|
||||||
if (!*best_parent_clk || tmp_rate > best_rate) {
|
if (!req->best_parent_hw || tmp_rate > best_rate) {
|
||||||
*best_parent_clk = __clk_get_hw(parent);
|
req->best_parent_hw = __clk_get_hw(parent);
|
||||||
*best_parent_rate = parent_rate;
|
req->best_parent_rate = parent_rate;
|
||||||
best_rate = tmp_rate;
|
best_rate = tmp_rate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (best_rate < 0)
|
||||||
return best_rate;
|
return best_rate;
|
||||||
|
|
||||||
|
req->rate = best_rate;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ar100_set_parent(struct clk_hw *hw, u8 index)
|
static int ar100_set_parent(struct clk_hw *hw, u8 index)
|
||||||
|
|||||||
@@ -118,11 +118,8 @@ static long sun6i_ahb1_clk_round(unsigned long rate, u8 *divp, u8 *pre_divp,
|
|||||||
return (parent_rate / calcm) >> calcp;
|
return (parent_rate / calcm) >> calcp;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int sun6i_ahb1_clk_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req)
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_clk)
|
|
||||||
{
|
{
|
||||||
struct clk *clk = hw->clk, *parent, *best_parent = NULL;
|
struct clk *clk = hw->clk, *parent, *best_parent = NULL;
|
||||||
int i, num_parents;
|
int i, num_parents;
|
||||||
@@ -135,25 +132,28 @@ static long sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
if (!parent)
|
if (!parent)
|
||||||
continue;
|
continue;
|
||||||
if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
|
if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
|
||||||
parent_rate = __clk_round_rate(parent, rate);
|
parent_rate = __clk_round_rate(parent, req->rate);
|
||||||
else
|
else
|
||||||
parent_rate = __clk_get_rate(parent);
|
parent_rate = __clk_get_rate(parent);
|
||||||
|
|
||||||
child_rate = sun6i_ahb1_clk_round(rate, NULL, NULL, i,
|
child_rate = sun6i_ahb1_clk_round(req->rate, NULL, NULL, i,
|
||||||
parent_rate);
|
parent_rate);
|
||||||
|
|
||||||
if (child_rate <= rate && child_rate > best_child_rate) {
|
if (child_rate <= req->rate && child_rate > best_child_rate) {
|
||||||
best_parent = parent;
|
best_parent = parent;
|
||||||
best = parent_rate;
|
best = parent_rate;
|
||||||
best_child_rate = child_rate;
|
best_child_rate = child_rate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (best_parent)
|
if (!best_parent)
|
||||||
*best_parent_clk = __clk_get_hw(best_parent);
|
return -EINVAL;
|
||||||
*best_parent_rate = best;
|
|
||||||
|
|
||||||
return best_child_rate;
|
req->best_parent_hw = __clk_get_hw(best_parent);
|
||||||
|
req->best_parent_rate = best;
|
||||||
|
req->rate = best_child_rate;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sun6i_ahb1_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
static int sun6i_ahb1_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
|||||||
@@ -116,11 +116,7 @@ static unsigned long emc_recalc_rate(struct clk_hw *hw,
|
|||||||
* safer since things have EMC rate floors. Also don't touch parent_rate
|
* safer since things have EMC rate floors. Also don't touch parent_rate
|
||||||
* since we don't want the CCF to play with our parent clocks.
|
* since we don't want the CCF to play with our parent clocks.
|
||||||
*/
|
*/
|
||||||
static long emc_determine_rate(struct clk_hw *hw, unsigned long rate,
|
static int emc_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
|
||||||
unsigned long min_rate,
|
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_hw)
|
|
||||||
{
|
{
|
||||||
struct tegra_clk_emc *tegra;
|
struct tegra_clk_emc *tegra;
|
||||||
u8 ram_code = tegra_read_ram_code();
|
u8 ram_code = tegra_read_ram_code();
|
||||||
@@ -135,22 +131,28 @@ static long emc_determine_rate(struct clk_hw *hw, unsigned long rate,
|
|||||||
|
|
||||||
timing = tegra->timings + i;
|
timing = tegra->timings + i;
|
||||||
|
|
||||||
if (timing->rate > max_rate) {
|
if (timing->rate > req->max_rate) {
|
||||||
i = min(i, 1);
|
i = min(i, 1);
|
||||||
return tegra->timings[i - 1].rate;
|
req->rate = tegra->timings[i - 1].rate;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timing->rate < min_rate)
|
if (timing->rate < req->min_rate)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (timing->rate >= rate)
|
if (timing->rate >= req->rate) {
|
||||||
return timing->rate;
|
req->rate = timing->rate;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (timing)
|
if (timing) {
|
||||||
return timing->rate;
|
req->rate = timing->rate;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return __clk_get_rate(hw->clk);
|
req->rate = __clk_get_rate(hw->clk);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u8 emc_get_parent(struct clk_hw *hw)
|
static u8 emc_get_parent(struct clk_hw *hw)
|
||||||
|
|||||||
@@ -37,6 +37,28 @@ struct clk_hw;
|
|||||||
struct clk_core;
|
struct clk_core;
|
||||||
struct dentry;
|
struct dentry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct clk_rate_request - Structure encoding the clk constraints that
|
||||||
|
* a clock user might require.
|
||||||
|
*
|
||||||
|
* @rate: Requested clock rate. This field will be adjusted by
|
||||||
|
* clock drivers according to hardware capabilities.
|
||||||
|
* @min_rate: Minimum rate imposed by clk users.
|
||||||
|
* @max_rate: Maximum rate a imposed by clk users.
|
||||||
|
* @best_parent_rate: The best parent rate a parent can provide to fulfill the
|
||||||
|
* requested constraints.
|
||||||
|
* @best_parent_hw: The most appropriate parent clock that fulfills the
|
||||||
|
* requested constraints.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct clk_rate_request {
|
||||||
|
unsigned long rate;
|
||||||
|
unsigned long min_rate;
|
||||||
|
unsigned long max_rate;
|
||||||
|
unsigned long best_parent_rate;
|
||||||
|
struct clk_hw *best_parent_hw;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct clk_ops - Callback operations for hardware clocks; these are to
|
* struct clk_ops - Callback operations for hardware clocks; these are to
|
||||||
* be provided by the clock implementation, and will be called by drivers
|
* be provided by the clock implementation, and will be called by drivers
|
||||||
@@ -176,12 +198,8 @@ struct clk_ops {
|
|||||||
unsigned long parent_rate);
|
unsigned long parent_rate);
|
||||||
long (*round_rate)(struct clk_hw *hw, unsigned long rate,
|
long (*round_rate)(struct clk_hw *hw, unsigned long rate,
|
||||||
unsigned long *parent_rate);
|
unsigned long *parent_rate);
|
||||||
long (*determine_rate)(struct clk_hw *hw,
|
int (*determine_rate)(struct clk_hw *hw,
|
||||||
unsigned long rate,
|
struct clk_rate_request *req);
|
||||||
unsigned long min_rate,
|
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_hw);
|
|
||||||
int (*set_parent)(struct clk_hw *hw, u8 index);
|
int (*set_parent)(struct clk_hw *hw, u8 index);
|
||||||
u8 (*get_parent)(struct clk_hw *hw);
|
u8 (*get_parent)(struct clk_hw *hw);
|
||||||
int (*set_rate)(struct clk_hw *hw, unsigned long rate,
|
int (*set_rate)(struct clk_hw *hw, unsigned long rate,
|
||||||
@@ -595,20 +613,11 @@ unsigned long __clk_get_flags(struct clk *clk);
|
|||||||
bool __clk_is_prepared(struct clk *clk);
|
bool __clk_is_prepared(struct clk *clk);
|
||||||
bool __clk_is_enabled(struct clk *clk);
|
bool __clk_is_enabled(struct clk *clk);
|
||||||
struct clk *__clk_lookup(const char *name);
|
struct clk *__clk_lookup(const char *name);
|
||||||
long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
|
int __clk_mux_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long min_rate,
|
struct clk_rate_request *req);
|
||||||
unsigned long max_rate,
|
int __clk_determine_rate(struct clk_hw *core, struct clk_rate_request *req);
|
||||||
unsigned long *best_parent_rate,
|
int __clk_mux_determine_rate_closest(struct clk_hw *hw,
|
||||||
struct clk_hw **best_parent_p);
|
struct clk_rate_request *req);
|
||||||
unsigned long __clk_determine_rate(struct clk_hw *core,
|
|
||||||
unsigned long rate,
|
|
||||||
unsigned long min_rate,
|
|
||||||
unsigned long max_rate);
|
|
||||||
long __clk_mux_determine_rate_closest(struct clk_hw *hw, unsigned long rate,
|
|
||||||
unsigned long min_rate,
|
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_p);
|
|
||||||
void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent);
|
void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent);
|
||||||
|
|
||||||
static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src)
|
static inline void __clk_hw_set_clk(struct clk_hw *dst, struct clk_hw *src)
|
||||||
|
|||||||
@@ -269,23 +269,15 @@ int omap3_noncore_dpll_set_rate_and_parent(struct clk_hw *hw,
|
|||||||
unsigned long rate,
|
unsigned long rate,
|
||||||
unsigned long parent_rate,
|
unsigned long parent_rate,
|
||||||
u8 index);
|
u8 index);
|
||||||
long omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
|
int omap3_noncore_dpll_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long rate,
|
struct clk_rate_request *req);
|
||||||
unsigned long min_rate,
|
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_clk);
|
|
||||||
unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
|
unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
|
||||||
unsigned long parent_rate);
|
unsigned long parent_rate);
|
||||||
long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
|
long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
|
||||||
unsigned long target_rate,
|
unsigned long target_rate,
|
||||||
unsigned long *parent_rate);
|
unsigned long *parent_rate);
|
||||||
long omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
|
int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
|
||||||
unsigned long rate,
|
struct clk_rate_request *req);
|
||||||
unsigned long min_rate,
|
|
||||||
unsigned long max_rate,
|
|
||||||
unsigned long *best_parent_rate,
|
|
||||||
struct clk_hw **best_parent_clk);
|
|
||||||
u8 omap2_init_dpll_parent(struct clk_hw *hw);
|
u8 omap2_init_dpll_parent(struct clk_hw *hw);
|
||||||
unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
|
unsigned long omap3_dpll_recalc(struct clk_hw *hw, unsigned long parent_rate);
|
||||||
long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
|
long omap2_dpll_round_rate(struct clk_hw *hw, unsigned long target_rate,
|
||||||
|
|||||||
Reference in New Issue
Block a user