Commit 364a609d authored by Stephen Boyd's avatar Stephen Boyd

Merge tag 'sunxi-clk-for-6.6-2' of...

Merge tag 'sunxi-clk-for-6.6-2' of https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux into clk-allwinner

Pull Allwinner clk driver changes from Chen-Yu Tsai:

 - Parameter name correction for ccu_nkm_round_rate()
 - Implement CLK_SET_RATE_PARENT for NKM clocks, i.e. consider alternative
   parent rates when determining clock rates
 - Set CLK_SET_RATE_PARENT for A64 pll-mipi
 - Support finding closest (as opposed to closest but not higher) clock
   rate for NM, NKM, mux and div type clocks, as use it for A64
   pll-video0
 - Prefer current parent rate if able to generate ideal clock rate for
   NKM clocks

* tag 'sunxi-clk-for-6.6-2' of https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux:
  clk: sunxi-ng: nkm: Prefer current parent rate
  clk: sunxi-ng: a64: select closest rate for pll-video0
  clk: sunxi-ng: div: Support finding closest rate
  clk: sunxi-ng: mux: Support finding closest rate
  clk: sunxi-ng: nkm: Support finding closest rate
  clk: sunxi-ng: nm: Support finding closest rate
  clk: sunxi-ng: Add helper function to find closest rate
  clk: sunxi-ng: Add feature to find closest rate
  clk: sunxi-ng: a64: allow pll-mipi to set parent's rate
  clk: sunxi-ng: nkm: consider alternative parent rates when determining rate
  clk: sunxi-ng: nkm: Use correct parameter name for parent HW
parents 7458ea38 a69f9463
...@@ -68,7 +68,7 @@ static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", ...@@ -68,7 +68,7 @@ static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
BIT(28), /* lock */ BIT(28), /* lock */
CLK_SET_RATE_UNGATE); CLK_SET_RATE_UNGATE);
static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video0_clk, "pll-video0", static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST(pll_video0_clk, "pll-video0",
"osc24M", 0x010, "osc24M", 0x010,
192000000, /* Minimum rate */ 192000000, /* Minimum rate */
1008000000, /* Maximum rate */ 1008000000, /* Maximum rate */
...@@ -179,7 +179,9 @@ static struct ccu_nkm pll_mipi_clk = { ...@@ -179,7 +179,9 @@ static struct ccu_nkm pll_mipi_clk = {
.common = { .common = {
.reg = 0x040, .reg = 0x040,
.hw.init = CLK_HW_INIT("pll-mipi", "pll-video0", .hw.init = CLK_HW_INIT("pll-mipi", "pll-video0",
&ccu_nkm_ops, CLK_SET_RATE_UNGATE), &ccu_nkm_ops,
CLK_SET_RATE_UNGATE | CLK_SET_RATE_PARENT),
.features = CCU_FEATURE_CLOSEST_RATE,
}, },
}; };
...@@ -536,25 +538,18 @@ static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, ...@@ -536,25 +538,18 @@ static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" }; static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" };
static const u8 tcon0_table[] = { 0, 2, }; static const u8 tcon0_table[] = { 0, 2, };
static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents, static SUNXI_CCU_MUX_TABLE_WITH_GATE_CLOSEST(tcon0_clk, "tcon0", tcon0_parents,
tcon0_table, 0x118, 24, 3, BIT(31), tcon0_table, 0x118, 24, 3, BIT(31),
CLK_SET_RATE_PARENT | CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT);
CLK_SET_RATE_NO_REPARENT);
static const char * const tcon1_parents[] = { "pll-video0", "pll-video1" }; static const char * const tcon1_parents[] = { "pll-video0", "pll-video1" };
static const u8 tcon1_table[] = { 0, 2, }; static const u8 tcon1_table[] = { 0, 2, };
static struct ccu_div tcon1_clk = { static SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(tcon1_clk, "tcon1", tcon1_parents,
.enable = BIT(31), tcon1_table, 0x11c,
.div = _SUNXI_CCU_DIV(0, 4), 0, 4, /* M */
.mux = _SUNXI_CCU_MUX_TABLE(24, 2, tcon1_table), 24, 2, /* mux */
.common = { BIT(31), /* gate */
.reg = 0x11c, CLK_SET_RATE_PARENT);
.hw.init = CLK_HW_INIT_PARENTS("tcon1",
tcon1_parents,
&ccu_div_ops,
CLK_SET_RATE_PARENT),
},
};
static const char * const deinterlace_parents[] = { "pll-periph0", "pll-periph1" }; static const char * const deinterlace_parents[] = { "pll-periph0", "pll-periph1" };
static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", deinterlace_parents, static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", deinterlace_parents,
...@@ -584,7 +579,7 @@ static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", ...@@ -584,7 +579,7 @@ static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M",
0x144, BIT(31), 0); 0x144, BIT(31), 0);
static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" }; static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" };
static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, static SUNXI_CCU_M_WITH_MUX_GATE_CLOSEST(hdmi_clk, "hdmi", hdmi_parents,
0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT); 0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
static SUNXI_CCU_GATE(hdmi_ddc_clk, "hdmi-ddc", "osc24M", static SUNXI_CCU_GATE(hdmi_ddc_clk, "hdmi-ddc", "osc24M",
...@@ -597,7 +592,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, ...@@ -597,7 +592,7 @@ static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
static const char * const dsi_dphy_parents[] = { "pll-video0", "pll-periph0" }; static const char * const dsi_dphy_parents[] = { "pll-video0", "pll-periph0" };
static const u8 dsi_dphy_table[] = { 0, 2, }; static const u8 dsi_dphy_table[] = { 0, 2, };
static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(dsi_dphy_clk, "dsi-dphy", static SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(dsi_dphy_clk, "dsi-dphy",
dsi_dphy_parents, dsi_dphy_table, dsi_dphy_parents, dsi_dphy_table,
0x168, 0, 4, 8, 2, BIT(15), CLK_SET_RATE_PARENT); 0x168, 0, 4, 8, 2, BIT(15), CLK_SET_RATE_PARENT);
......
...@@ -39,6 +39,18 @@ void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock) ...@@ -39,6 +39,18 @@ void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock)
} }
EXPORT_SYMBOL_NS_GPL(ccu_helper_wait_for_lock, SUNXI_CCU); EXPORT_SYMBOL_NS_GPL(ccu_helper_wait_for_lock, SUNXI_CCU);
bool ccu_is_better_rate(struct ccu_common *common,
unsigned long target_rate,
unsigned long current_rate,
unsigned long best_rate)
{
if (common->features & CCU_FEATURE_CLOSEST_RATE)
return abs(current_rate - target_rate) < abs(best_rate - target_rate);
return current_rate <= target_rate && current_rate > best_rate;
}
EXPORT_SYMBOL_NS_GPL(ccu_is_better_rate, SUNXI_CCU);
/* /*
* This clock notifier is called when the frequency of a PLL clock is * This clock notifier is called when the frequency of a PLL clock is
* changed. In common PLL designs, changes to the dividers take effect * changed. In common PLL designs, changes to the dividers take effect
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#define CCU_FEATURE_MMC_TIMING_SWITCH BIT(6) #define CCU_FEATURE_MMC_TIMING_SWITCH BIT(6)
#define CCU_FEATURE_SIGMA_DELTA_MOD BIT(7) #define CCU_FEATURE_SIGMA_DELTA_MOD BIT(7)
#define CCU_FEATURE_KEY_FIELD BIT(8) #define CCU_FEATURE_KEY_FIELD BIT(8)
#define CCU_FEATURE_CLOSEST_RATE BIT(9)
/* MMC timing mode switch bit */ /* MMC timing mode switch bit */
#define CCU_MMC_NEW_TIMING_MODE BIT(30) #define CCU_MMC_NEW_TIMING_MODE BIT(30)
...@@ -52,6 +53,11 @@ struct sunxi_ccu_desc { ...@@ -52,6 +53,11 @@ struct sunxi_ccu_desc {
void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock); void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock);
bool ccu_is_better_rate(struct ccu_common *common,
unsigned long target_rate,
unsigned long current_rate,
unsigned long best_rate);
struct ccu_pll_nb { struct ccu_pll_nb {
struct notifier_block clk_nb; struct notifier_block clk_nb;
struct ccu_common *common; struct ccu_common *common;
......
...@@ -143,6 +143,26 @@ struct ccu_div { ...@@ -143,6 +143,26 @@ struct ccu_div {
}, \ }, \
} }
#define SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(_struct, _name, \
_parents, _table, \
_reg, \
_mshift, _mwidth, \
_muxshift, _muxwidth, \
_gate, _flags) \
struct ccu_div _struct = { \
.enable = _gate, \
.div = _SUNXI_CCU_DIV_FLAGS(_mshift, _mwidth, CLK_DIVIDER_ROUND_CLOSEST), \
.mux = _SUNXI_CCU_MUX_TABLE(_muxshift, _muxwidth, _table), \
.common = { \
.reg = _reg, \
.hw.init = CLK_HW_INIT_PARENTS(_name, \
_parents, \
&ccu_div_ops, \
_flags), \
.features = CCU_FEATURE_CLOSEST_RATE, \
}, \
}
#define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg, \ #define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg, \
_mshift, _mwidth, _muxshift, _muxwidth, \ _mshift, _mwidth, _muxshift, _muxwidth, \
_gate, _flags) \ _gate, _flags) \
...@@ -152,6 +172,16 @@ struct ccu_div { ...@@ -152,6 +172,16 @@ struct ccu_div {
_muxshift, _muxwidth, \ _muxshift, _muxwidth, \
_gate, _flags) _gate, _flags)
#define SUNXI_CCU_M_WITH_MUX_GATE_CLOSEST(_struct, _name, _parents, \
_reg, _mshift, _mwidth, \
_muxshift, _muxwidth, \
_gate, _flags) \
SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(_struct, _name, \
_parents, NULL, \
_reg, _mshift, _mwidth, \
_muxshift, _muxwidth, \
_gate, _flags)
#define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg, \ #define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg, \
_mshift, _mwidth, _muxshift, _muxwidth, \ _mshift, _mwidth, _muxshift, _muxwidth, \
_flags) \ _flags) \
......
...@@ -139,7 +139,7 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common, ...@@ -139,7 +139,7 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common,
goto out; goto out;
} }
if ((req->rate - tmp_rate) < (req->rate - best_rate)) { if (ccu_is_better_rate(common, req->rate, tmp_rate, best_rate)) {
best_rate = tmp_rate; best_rate = tmp_rate;
best_parent_rate = parent_rate; best_parent_rate = parent_rate;
best_parent = parent; best_parent = parent;
...@@ -242,6 +242,17 @@ static int ccu_mux_set_parent(struct clk_hw *hw, u8 index) ...@@ -242,6 +242,17 @@ static int ccu_mux_set_parent(struct clk_hw *hw, u8 index)
return ccu_mux_helper_set_parent(&cm->common, &cm->mux, index); return ccu_mux_helper_set_parent(&cm->common, &cm->mux, index);
} }
static int ccu_mux_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
struct ccu_mux *cm = hw_to_ccu_mux(hw);
if (cm->common.features & CCU_FEATURE_CLOSEST_RATE)
return clk_mux_determine_rate_flags(hw, req, CLK_MUX_ROUND_CLOSEST);
return clk_mux_determine_rate_flags(hw, req, 0);
}
static unsigned long ccu_mux_recalc_rate(struct clk_hw *hw, static unsigned long ccu_mux_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate) unsigned long parent_rate)
{ {
...@@ -259,7 +270,7 @@ const struct clk_ops ccu_mux_ops = { ...@@ -259,7 +270,7 @@ const struct clk_ops ccu_mux_ops = {
.get_parent = ccu_mux_get_parent, .get_parent = ccu_mux_get_parent,
.set_parent = ccu_mux_set_parent, .set_parent = ccu_mux_set_parent,
.determine_rate = __clk_mux_determine_rate, .determine_rate = ccu_mux_determine_rate,
.recalc_rate = ccu_mux_recalc_rate, .recalc_rate = ccu_mux_recalc_rate,
}; };
EXPORT_SYMBOL_NS_GPL(ccu_mux_ops, SUNXI_CCU); EXPORT_SYMBOL_NS_GPL(ccu_mux_ops, SUNXI_CCU);
......
...@@ -46,9 +46,9 @@ struct ccu_mux { ...@@ -46,9 +46,9 @@ struct ccu_mux {
struct ccu_common common; struct ccu_common common;
}; };
#define SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, _table, \ #define SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents, _table, \
_reg, _shift, _width, _gate, \ _reg, _shift, _width, _gate, \
_flags) \ _flags, _features) \
struct ccu_mux _struct = { \ struct ccu_mux _struct = { \
.enable = _gate, \ .enable = _gate, \
.mux = _SUNXI_CCU_MUX_TABLE(_shift, _width, _table), \ .mux = _SUNXI_CCU_MUX_TABLE(_shift, _width, _table), \
...@@ -58,9 +58,25 @@ struct ccu_mux { ...@@ -58,9 +58,25 @@ struct ccu_mux {
_parents, \ _parents, \
&ccu_mux_ops, \ &ccu_mux_ops, \
_flags), \ _flags), \
.features = _features, \
} \ } \
} }
#define SUNXI_CCU_MUX_TABLE_WITH_GATE_CLOSEST(_struct, _name, _parents, \
_table, _reg, _shift, \
_width, _gate, _flags) \
SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents, \
_table, _reg, _shift, \
_width, _gate, _flags, \
CCU_FEATURE_CLOSEST_RATE)
#define SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, _table, \
_reg, _shift, _width, _gate, \
_flags) \
SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents, \
_table, _reg, _shift, \
_width, _gate, _flags, 0)
#define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg, \ #define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg, \
_shift, _width, _gate, _flags) \ _shift, _width, _gate, _flags) \
SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL, \ SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL, \
......
...@@ -16,8 +16,47 @@ struct _ccu_nkm { ...@@ -16,8 +16,47 @@ struct _ccu_nkm {
unsigned long m, min_m, max_m; unsigned long m, min_m, max_m;
}; };
static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate, static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common *common,
struct clk_hw *parent_hw,
unsigned long *parent, unsigned long rate,
struct _ccu_nkm *nkm) struct _ccu_nkm *nkm)
{
unsigned long best_rate = 0, best_parent_rate = *parent, tmp_parent = *parent;
unsigned long best_n = 0, best_k = 0, best_m = 0;
unsigned long _n, _k, _m;
for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
unsigned long tmp_rate;
tmp_parent = clk_hw_round_rate(parent_hw, rate * _m / (_n * _k));
tmp_rate = tmp_parent * _n * _k / _m;
if (ccu_is_better_rate(common, rate, tmp_rate, best_rate) ||
(tmp_parent == *parent && tmp_rate == best_rate)) {
best_rate = tmp_rate;
best_parent_rate = tmp_parent;
best_n = _n;
best_k = _k;
best_m = _m;
}
}
}
}
nkm->n = best_n;
nkm->k = best_k;
nkm->m = best_m;
*parent = best_parent_rate;
return best_rate;
}
static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate,
struct _ccu_nkm *nkm, struct ccu_common *common)
{ {
unsigned long best_rate = 0; unsigned long best_rate = 0;
unsigned long best_n = 0, best_k = 0, best_m = 0; unsigned long best_n = 0, best_k = 0, best_m = 0;
...@@ -30,9 +69,7 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate, ...@@ -30,9 +69,7 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate,
tmp_rate = parent * _n * _k / _m; tmp_rate = parent * _n * _k / _m;
if (tmp_rate > rate) if (ccu_is_better_rate(common, rate, tmp_rate, best_rate)) {
continue;
if ((rate - tmp_rate) < (rate - best_rate)) {
best_rate = tmp_rate; best_rate = tmp_rate;
best_n = _n; best_n = _n;
best_k = _k; best_k = _k;
...@@ -106,7 +143,7 @@ static unsigned long ccu_nkm_recalc_rate(struct clk_hw *hw, ...@@ -106,7 +143,7 @@ static unsigned long ccu_nkm_recalc_rate(struct clk_hw *hw,
} }
static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux, static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
struct clk_hw *hw, struct clk_hw *parent_hw,
unsigned long *parent_rate, unsigned long *parent_rate,
unsigned long rate, unsigned long rate,
void *data) void *data)
...@@ -124,7 +161,11 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux, ...@@ -124,7 +161,11 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate *= nkm->fixed_post_div; rate *= nkm->fixed_post_div;
rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm); if (!clk_hw_can_set_rate_parent(&nkm->common.hw))
rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm, &nkm->common);
else
rate = ccu_nkm_find_best_with_parent_adj(&nkm->common, parent_hw, parent_rate, rate,
&_nkm);
if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate /= nkm->fixed_post_div; rate /= nkm->fixed_post_div;
...@@ -159,7 +200,7 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -159,7 +200,7 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
_nkm.min_m = 1; _nkm.min_m = 1;
_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
ccu_nkm_find_best(parent_rate, rate, &_nkm); ccu_nkm_find_best(parent_rate, rate, &_nkm, &nkm->common);
spin_lock_irqsave(nkm->common.lock, flags); spin_lock_irqsave(nkm->common.lock, flags);
......
...@@ -27,8 +27,8 @@ static unsigned long ccu_nm_calc_rate(unsigned long parent, ...@@ -27,8 +27,8 @@ static unsigned long ccu_nm_calc_rate(unsigned long parent,
return rate; return rate;
} }
static unsigned long ccu_nm_find_best(unsigned long parent, unsigned long rate, static unsigned long ccu_nm_find_best(struct ccu_common *common, unsigned long parent,
struct _ccu_nm *nm) unsigned long rate, struct _ccu_nm *nm)
{ {
unsigned long best_rate = 0; unsigned long best_rate = 0;
unsigned long best_n = 0, best_m = 0; unsigned long best_n = 0, best_m = 0;
...@@ -39,10 +39,7 @@ static unsigned long ccu_nm_find_best(unsigned long parent, unsigned long rate, ...@@ -39,10 +39,7 @@ static unsigned long ccu_nm_find_best(unsigned long parent, unsigned long rate,
unsigned long tmp_rate = ccu_nm_calc_rate(parent, unsigned long tmp_rate = ccu_nm_calc_rate(parent,
_n, _m); _n, _m);
if (tmp_rate > rate) if (ccu_is_better_rate(common, rate, tmp_rate, best_rate)) {
continue;
if ((rate - tmp_rate) < (rate - best_rate)) {
best_rate = tmp_rate; best_rate = tmp_rate;
best_n = _n; best_n = _n;
best_m = _m; best_m = _m;
...@@ -159,7 +156,7 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate, ...@@ -159,7 +156,7 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
_nm.min_m = 1; _nm.min_m = 1;
_nm.max_m = nm->m.max ?: 1 << nm->m.width; _nm.max_m = nm->m.max ?: 1 << nm->m.width;
rate = ccu_nm_find_best(*parent_rate, rate, &_nm); rate = ccu_nm_find_best(&nm->common, *parent_rate, rate, &_nm);
if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV) if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
rate /= nm->fixed_post_div; rate /= nm->fixed_post_div;
...@@ -210,7 +207,7 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate, ...@@ -210,7 +207,7 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
&_nm.m, &_nm.n); &_nm.m, &_nm.n);
} else { } else {
ccu_sdm_helper_disable(&nm->common, &nm->sdm); ccu_sdm_helper_disable(&nm->common, &nm->sdm);
ccu_nm_find_best(parent_rate, rate, &_nm); ccu_nm_find_best(&nm->common, parent_rate, rate, &_nm);
} }
spin_lock_irqsave(nm->common.lock, flags); spin_lock_irqsave(nm->common.lock, flags);
......
...@@ -108,7 +108,7 @@ struct ccu_nm { ...@@ -108,7 +108,7 @@ struct ccu_nm {
}, \ }, \
} }
#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(_struct, _name, \ #define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT(_struct, _name, \
_parent, _reg, \ _parent, _reg, \
_min_rate, _max_rate, \ _min_rate, _max_rate, \
_nshift, _nwidth, \ _nshift, _nwidth, \
...@@ -116,7 +116,8 @@ struct ccu_nm { ...@@ -116,7 +116,8 @@ struct ccu_nm {
_frac_en, _frac_sel, \ _frac_en, _frac_sel, \
_frac_rate_0, \ _frac_rate_0, \
_frac_rate_1, \ _frac_rate_1, \
_gate, _lock, _flags) \ _gate, _lock, _flags, \
_features) \
struct ccu_nm _struct = { \ struct ccu_nm _struct = { \
.enable = _gate, \ .enable = _gate, \
.lock = _lock, \ .lock = _lock, \
...@@ -129,7 +130,7 @@ struct ccu_nm { ...@@ -129,7 +130,7 @@ struct ccu_nm {
.max_rate = _max_rate, \ .max_rate = _max_rate, \
.common = { \ .common = { \
.reg = _reg, \ .reg = _reg, \
.features = CCU_FEATURE_FRACTIONAL, \ .features = _features, \
.hw.init = CLK_HW_INIT(_name, \ .hw.init = CLK_HW_INIT(_name, \
_parent, \ _parent, \
&ccu_nm_ops, \ &ccu_nm_ops, \
...@@ -137,6 +138,47 @@ struct ccu_nm { ...@@ -137,6 +138,47 @@ struct ccu_nm {
}, \ }, \
} }
#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(_struct, _name, \
_parent, _reg, \
_min_rate, _max_rate, \
_nshift, _nwidth, \
_mshift, _mwidth, \
_frac_en, _frac_sel, \
_frac_rate_0, \
_frac_rate_1, \
_gate, _lock, _flags) \
SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT(_struct, _name, \
_parent, _reg, \
_min_rate, _max_rate, \
_nshift, _nwidth, \
_mshift, _mwidth, \
_frac_en, _frac_sel, \
_frac_rate_0, \
_frac_rate_1, \
_gate, _lock, _flags, \
CCU_FEATURE_FRACTIONAL)
#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST(_struct, _name, \
_parent, _reg, \
_min_rate, _max_rate, \
_nshift, _nwidth, \
_mshift, _mwidth, \
_frac_en, _frac_sel, \
_frac_rate_0, \
_frac_rate_1, \
_gate, _lock, _flags) \
SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT(_struct, _name, \
_parent, _reg, \
_min_rate, _max_rate, \
_nshift, _nwidth, \
_mshift, _mwidth, \
_frac_en, _frac_sel, \
_frac_rate_0, \
_frac_rate_1, \
_gate, _lock, _flags, \
CCU_FEATURE_FRACTIONAL |\
CCU_FEATURE_CLOSEST_RATE)
#define SUNXI_CCU_NM_WITH_GATE_LOCK(_struct, _name, _parent, _reg, \ #define SUNXI_CCU_NM_WITH_GATE_LOCK(_struct, _name, _parent, _reg, \
_nshift, _nwidth, \ _nshift, _nwidth, \
_mshift, _mwidth, \ _mshift, _mwidth, \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment