mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-16 18:08:20 +00:00
Allwinner clock changes for 6.6 part 2
- 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 -----BEGIN PGP SIGNATURE----- iQJCBAABCgAsFiEE2nN1m/hhnkhOWjtHOJpUIZwPJDAFAmTY1aQOHHdlbnNAY3Np ZS5vcmcACgkQOJpUIZwPJDA7JA/+KUOF8mI4PClCsjDq0y+d0GPbW0b0cFVkAlY7 gYRSfzgKWiQEuls87cpUiVskKm5pADfvpDkB4eky7ijethwhwzjjEl7IKfDyzhwr XmjacWE+OVqMqwGObHorgz2bJWaeiPuh2ybh/MNt7taa7TgLHbx/atP+I8V69ovR bljHErTG21sRLsfpDxu2hVJaWVyY3tiibEm2751JoSq/xf/Lei07hSKuh3aVsJdm /j5YnWkOSMaICeYSxdhDprhBz1yMnSfVvOviTazXhSkkpTkJOz0eRu3dBN6xxrLP Y+mOxbt4xo/O2qflo0hyaTwzf/VNmgGqji2rKsCTdt2F2KwWpd8ropr+ssVKbO3B IqsHXGhiXrq7/LIxJ7AZtTnuY17f2VVx/5KiryngM6Got6zZPOqApJIoetckMXeZ TPGvcVWkDOXcCCArmgPEwIr9S+h15SJ0bc5F79go1e93b4BWTVDmCLQwVzeNdPLr Mrlnj3xGRh+adbx8BQYIkDo0XlO40DK5eak/bAZj7HmuIbMQNSv9A1BK6diFqqeF alao/io+6c4ezjJSaLWqzx7+ix4Gfkv0z8Ux0cSQj9+f9XQIITJmlRmsZvGFdkbC UaAJhCN7+Eg/LVhp1ifLTmcsEP04aCXuPPCfZ9NNfYj9f+aqE/5gF2XlE1KWbT+J lp0Edw4= =u5sg -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
364a609dc3
@ -68,7 +68,7 @@ static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
|
||||
BIT(28), /* lock */
|
||||
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,
|
||||
192000000, /* Minimum rate */
|
||||
1008000000, /* Maximum rate */
|
||||
@ -179,7 +179,9 @@ static struct ccu_nkm pll_mipi_clk = {
|
||||
.common = {
|
||||
.reg = 0x040,
|
||||
.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,
|
||||
|
||||
static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" };
|
||||
static const u8 tcon0_table[] = { 0, 2, };
|
||||
static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents,
|
||||
tcon0_table, 0x118, 24, 3, BIT(31),
|
||||
CLK_SET_RATE_PARENT |
|
||||
CLK_SET_RATE_NO_REPARENT);
|
||||
static SUNXI_CCU_MUX_TABLE_WITH_GATE_CLOSEST(tcon0_clk, "tcon0", tcon0_parents,
|
||||
tcon0_table, 0x118, 24, 3, BIT(31),
|
||||
CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT);
|
||||
|
||||
static const char * const tcon1_parents[] = { "pll-video0", "pll-video1" };
|
||||
static const u8 tcon1_table[] = { 0, 2, };
|
||||
static struct ccu_div tcon1_clk = {
|
||||
.enable = BIT(31),
|
||||
.div = _SUNXI_CCU_DIV(0, 4),
|
||||
.mux = _SUNXI_CCU_MUX_TABLE(24, 2, tcon1_table),
|
||||
.common = {
|
||||
.reg = 0x11c,
|
||||
.hw.init = CLK_HW_INIT_PARENTS("tcon1",
|
||||
tcon1_parents,
|
||||
&ccu_div_ops,
|
||||
CLK_SET_RATE_PARENT),
|
||||
},
|
||||
};
|
||||
static SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(tcon1_clk, "tcon1", tcon1_parents,
|
||||
tcon1_table, 0x11c,
|
||||
0, 4, /* M */
|
||||
24, 2, /* mux */
|
||||
BIT(31), /* gate */
|
||||
CLK_SET_RATE_PARENT);
|
||||
|
||||
static const char * const deinterlace_parents[] = { "pll-periph0", "pll-periph1" };
|
||||
static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", deinterlace_parents,
|
||||
@ -584,8 +579,8 @@ static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M",
|
||||
0x144, BIT(31), 0);
|
||||
|
||||
static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" };
|
||||
static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,
|
||||
0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
|
||||
static SUNXI_CCU_M_WITH_MUX_GATE_CLOSEST(hdmi_clk, "hdmi", hdmi_parents,
|
||||
0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
|
||||
|
||||
static SUNXI_CCU_GATE(hdmi_ddc_clk, "hdmi-ddc", "osc24M",
|
||||
0x154, BIT(31), 0);
|
||||
@ -597,9 +592,9 @@ 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 u8 dsi_dphy_table[] = { 0, 2, };
|
||||
static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(dsi_dphy_clk, "dsi-dphy",
|
||||
dsi_dphy_parents, dsi_dphy_table,
|
||||
0x168, 0, 4, 8, 2, BIT(15), CLK_SET_RATE_PARENT);
|
||||
static SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(dsi_dphy_clk, "dsi-dphy",
|
||||
dsi_dphy_parents, dsi_dphy_table,
|
||||
0x168, 0, 4, 8, 2, BIT(15), CLK_SET_RATE_PARENT);
|
||||
|
||||
static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu",
|
||||
0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT);
|
||||
|
@ -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);
|
||||
|
||||
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
|
||||
* changed. In common PLL designs, changes to the dividers take effect
|
||||
|
@ -18,6 +18,7 @@
|
||||
#define CCU_FEATURE_MMC_TIMING_SWITCH BIT(6)
|
||||
#define CCU_FEATURE_SIGMA_DELTA_MOD BIT(7)
|
||||
#define CCU_FEATURE_KEY_FIELD BIT(8)
|
||||
#define CCU_FEATURE_CLOSEST_RATE BIT(9)
|
||||
|
||||
/* MMC timing mode switch bit */
|
||||
#define CCU_MMC_NEW_TIMING_MODE BIT(30)
|
||||
@ -52,6 +53,11 @@ struct sunxi_ccu_desc {
|
||||
|
||||
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 notifier_block clk_nb;
|
||||
struct ccu_common *common;
|
||||
|
@ -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, \
|
||||
_mshift, _mwidth, _muxshift, _muxwidth, \
|
||||
_gate, _flags) \
|
||||
@ -152,6 +172,16 @@ struct ccu_div {
|
||||
_muxshift, _muxwidth, \
|
||||
_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, \
|
||||
_mshift, _mwidth, _muxshift, _muxwidth, \
|
||||
_flags) \
|
||||
|
@ -139,7 +139,7 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common,
|
||||
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_parent_rate = parent_rate;
|
||||
best_parent = parent;
|
||||
@ -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);
|
||||
}
|
||||
|
||||
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,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
@ -259,7 +270,7 @@ const struct clk_ops ccu_mux_ops = {
|
||||
.get_parent = ccu_mux_get_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,
|
||||
};
|
||||
EXPORT_SYMBOL_NS_GPL(ccu_mux_ops, SUNXI_CCU);
|
||||
|
@ -46,20 +46,36 @@ struct ccu_mux {
|
||||
struct ccu_common common;
|
||||
};
|
||||
|
||||
#define SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents, _table, \
|
||||
_reg, _shift, _width, _gate, \
|
||||
_flags, _features) \
|
||||
struct ccu_mux _struct = { \
|
||||
.enable = _gate, \
|
||||
.mux = _SUNXI_CCU_MUX_TABLE(_shift, _width, _table), \
|
||||
.common = { \
|
||||
.reg = _reg, \
|
||||
.hw.init = CLK_HW_INIT_PARENTS(_name, \
|
||||
_parents, \
|
||||
&ccu_mux_ops, \
|
||||
_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) \
|
||||
struct ccu_mux _struct = { \
|
||||
.enable = _gate, \
|
||||
.mux = _SUNXI_CCU_MUX_TABLE(_shift, _width, _table), \
|
||||
.common = { \
|
||||
.reg = _reg, \
|
||||
.hw.init = CLK_HW_INIT_PARENTS(_name, \
|
||||
_parents, \
|
||||
&ccu_mux_ops, \
|
||||
_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, \
|
||||
_shift, _width, _gate, _flags) \
|
||||
|
@ -16,8 +16,47 @@ struct _ccu_nkm {
|
||||
unsigned long m, min_m, max_m;
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
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_nkm *nkm, struct ccu_common *common)
|
||||
{
|
||||
unsigned long best_rate = 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,
|
||||
|
||||
tmp_rate = parent * _n * _k / _m;
|
||||
|
||||
if (tmp_rate > rate)
|
||||
continue;
|
||||
if ((rate - tmp_rate) < (rate - best_rate)) {
|
||||
if (ccu_is_better_rate(common, rate, tmp_rate, best_rate)) {
|
||||
best_rate = tmp_rate;
|
||||
best_n = _n;
|
||||
best_k = _k;
|
||||
@ -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,
|
||||
struct clk_hw *hw,
|
||||
struct clk_hw *parent_hw,
|
||||
unsigned long *parent_rate,
|
||||
unsigned long rate,
|
||||
void *data)
|
||||
@ -124,7 +161,11 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
|
||||
if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
|
||||
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)
|
||||
rate /= nkm->fixed_post_div;
|
||||
@ -159,7 +200,7 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
_nkm.min_m = 1;
|
||||
_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);
|
||||
|
||||
|
@ -27,8 +27,8 @@ static unsigned long ccu_nm_calc_rate(unsigned long parent,
|
||||
return rate;
|
||||
}
|
||||
|
||||
static unsigned long ccu_nm_find_best(unsigned long parent, unsigned long rate,
|
||||
struct _ccu_nm *nm)
|
||||
static unsigned long ccu_nm_find_best(struct ccu_common *common, unsigned long parent,
|
||||
unsigned long rate, struct _ccu_nm *nm)
|
||||
{
|
||||
unsigned long best_rate = 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,
|
||||
unsigned long tmp_rate = ccu_nm_calc_rate(parent,
|
||||
_n, _m);
|
||||
|
||||
if (tmp_rate > rate)
|
||||
continue;
|
||||
|
||||
if ((rate - tmp_rate) < (rate - best_rate)) {
|
||||
if (ccu_is_better_rate(common, rate, tmp_rate, best_rate)) {
|
||||
best_rate = tmp_rate;
|
||||
best_n = _n;
|
||||
best_m = _m;
|
||||
@ -159,7 +156,7 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
_nm.min_m = 1;
|
||||
_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)
|
||||
rate /= nm->fixed_post_div;
|
||||
@ -210,7 +207,7 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
&_nm.m, &_nm.n);
|
||||
} else {
|
||||
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);
|
||||
|
@ -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, \
|
||||
_min_rate, _max_rate, \
|
||||
_nshift, _nwidth, \
|
||||
@ -116,7 +116,8 @@ struct ccu_nm {
|
||||
_frac_en, _frac_sel, \
|
||||
_frac_rate_0, \
|
||||
_frac_rate_1, \
|
||||
_gate, _lock, _flags) \
|
||||
_gate, _lock, _flags, \
|
||||
_features) \
|
||||
struct ccu_nm _struct = { \
|
||||
.enable = _gate, \
|
||||
.lock = _lock, \
|
||||
@ -129,7 +130,7 @@ struct ccu_nm {
|
||||
.max_rate = _max_rate, \
|
||||
.common = { \
|
||||
.reg = _reg, \
|
||||
.features = CCU_FEATURE_FRACTIONAL, \
|
||||
.features = _features, \
|
||||
.hw.init = CLK_HW_INIT(_name, \
|
||||
_parent, \
|
||||
&ccu_nm_ops, \
|
||||
@ -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, \
|
||||
_nshift, _nwidth, \
|
||||
_mshift, _mwidth, \
|
||||
|
Loading…
x
Reference in New Issue
Block a user