2018-04-20 09:57:53

by Jerome Brunet

[permalink] [raw]
Subject: [PATCH 0/2] clk: meson: mpll: add round closest support

ATM, the mpll driver can only round the requested rate down, even if
rounding up would have provided a better approximation of the requested
rate.

This patchset adds a flag to enable rounding to the closest rate possible,
even if it means rounding up.

The flag is then enabled on the axg platform to improve the rates provided
to the audio subsystem.

Jerome Brunet (2):
clk: meson: mpll: add round closest support
clk: meson: axg: let mpll clocks round closest

drivers/clk/meson/axg.c | 4 ++++
drivers/clk/meson/clk-mpll.c | 25 ++++++++++++++++++++-----
drivers/clk/meson/clkc.h | 3 +++
3 files changed, 27 insertions(+), 5 deletions(-)

--
2.14.3



2018-04-20 09:57:53

by Jerome Brunet

[permalink] [raw]
Subject: [PATCH 2/2] clk: meson: axg: let mpll clocks round closest

Let the mpll dividers achieve the closest rate possible, even if
it means rounding the requested rate up.

This is done to improve the accuracy of the rates provided by these
plls to the audio subsystem

Signed-off-by: Jerome Brunet <[email protected]>
---
drivers/clk/meson/axg.c | 4 ++++
1 file changed, 4 insertions(+)

diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
index 5f5d468c1efe..bd4dbc696b88 100644
--- a/drivers/clk/meson/axg.c
+++ b/drivers/clk/meson/axg.c
@@ -461,6 +461,7 @@ static struct clk_regmap axg_mpll0_div = {
.width = 1,
},
.lock = &meson_clk_lock,
+ .flags = CLK_MESON_MPLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
.name = "mpll0_div",
@@ -507,6 +508,7 @@ static struct clk_regmap axg_mpll1_div = {
.width = 1,
},
.lock = &meson_clk_lock,
+ .flags = CLK_MESON_MPLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
.name = "mpll1_div",
@@ -553,6 +555,7 @@ static struct clk_regmap axg_mpll2_div = {
.width = 1,
},
.lock = &meson_clk_lock,
+ .flags = CLK_MESON_MPLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
.name = "mpll2_div",
@@ -599,6 +602,7 @@ static struct clk_regmap axg_mpll3_div = {
.width = 1,
},
.lock = &meson_clk_lock,
+ .flags = CLK_MESON_MPLL_ROUND_CLOSEST,
},
.hw.init = &(struct clk_init_data){
.name = "mpll3_div",
--
2.14.3


2018-04-20 09:58:23

by Jerome Brunet

[permalink] [raw]
Subject: [PATCH 1/2] clk: meson: mpll: add round closest support

Allow the mpll driver to round the requested rate up if
CLK_MESON_MPLL_ROUND_CLOSEST is set and it provides a rate closer to the
requested rate.

Signed-off-by: Jerome Brunet <[email protected]>
---
drivers/clk/meson/clk-mpll.c | 25 ++++++++++++++++++++-----
drivers/clk/meson/clkc.h | 3 +++
2 files changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
index 0df1227b65b3..4e5283eb892a 100644
--- a/drivers/clk/meson/clk-mpll.c
+++ b/drivers/clk/meson/clk-mpll.c
@@ -89,10 +89,23 @@ static long rate_from_params(unsigned long parent_rate,
static void params_from_rate(unsigned long requested_rate,
unsigned long parent_rate,
unsigned int *sdm,
- unsigned int *n2)
+ unsigned int *n2,
+ u8 flags)
{
uint64_t div = parent_rate;
- unsigned long rem = do_div(div, requested_rate);
+ uint64_t frac = do_div(div, requested_rate);
+ unsigned long rem;
+
+ frac *= SDM_DEN;
+ rem = do_div(frac, requested_rate);
+
+ /* Should we round up ? */
+ if (flags & CLK_MESON_MPLL_ROUND_CLOSEST
+ && rem > (requested_rate / 2)) {
+ frac = (frac + 1) % SDM_DEN;
+ if (frac == 0)
+ div += 1;
+ }

if (div < N2_MIN) {
*n2 = N2_MIN;
@@ -102,7 +115,7 @@ static void params_from_rate(unsigned long requested_rate,
*sdm = SDM_DEN - 1;
} else {
*n2 = div;
- *sdm = DIV_ROUND_UP_ULL((u64)rem * SDM_DEN, requested_rate);
+ *sdm = frac;
}
}

@@ -125,9 +138,11 @@ static long mpll_round_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long *parent_rate)
{
+ struct clk_regmap *clk = to_clk_regmap(hw);
+ struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk);
unsigned int sdm, n2;

- params_from_rate(rate, *parent_rate, &sdm, &n2);
+ params_from_rate(rate, *parent_rate, &sdm, &n2, mpll->flags);
return rate_from_params(*parent_rate, sdm, n2);
}

@@ -140,7 +155,7 @@ static int mpll_set_rate(struct clk_hw *hw,
unsigned int sdm, n2;
unsigned long flags = 0;

- params_from_rate(rate, parent_rate, &sdm, &n2);
+ params_from_rate(rate, parent_rate, &sdm, &n2, mpll->flags);

if (mpll->lock)
spin_lock_irqsave(mpll->lock, flags);
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
index 8fe73c4edca8..8cc265cd3d2b 100644
--- a/drivers/clk/meson/clkc.h
+++ b/drivers/clk/meson/clkc.h
@@ -97,8 +97,11 @@ struct meson_clk_mpll_data {
struct parm ssen;
struct parm misc;
spinlock_t *lock;
+ u8 flags;
};

+#define CLK_MESON_MPLL_ROUND_CLOSEST BIT(0)
+
struct meson_clk_audio_div_data {
struct parm div;
u8 flags;
--
2.14.3


2018-04-26 08:41:19

by Neil Armstrong

[permalink] [raw]
Subject: Re: [PATCH 1/2] clk: meson: mpll: add round closest support

On 20/04/2018 11:56, Jerome Brunet wrote:
> Allow the mpll driver to round the requested rate up if
> CLK_MESON_MPLL_ROUND_CLOSEST is set and it provides a rate closer to the
> requested rate.
>
> Signed-off-by: Jerome Brunet <[email protected]>
> ---
> drivers/clk/meson/clk-mpll.c | 25 ++++++++++++++++++++-----
> drivers/clk/meson/clkc.h | 3 +++
> 2 files changed, 23 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
> index 0df1227b65b3..4e5283eb892a 100644
> --- a/drivers/clk/meson/clk-mpll.c
> +++ b/drivers/clk/meson/clk-mpll.c
> @@ -89,10 +89,23 @@ static long rate_from_params(unsigned long parent_rate,
> static void params_from_rate(unsigned long requested_rate,
> unsigned long parent_rate,
> unsigned int *sdm,
> - unsigned int *n2)
> + unsigned int *n2,
> + u8 flags)
> {
> uint64_t div = parent_rate;
> - unsigned long rem = do_div(div, requested_rate);
> + uint64_t frac = do_div(div, requested_rate);
> + unsigned long rem;
> +
> + frac *= SDM_DEN;
> + rem = do_div(frac, requested_rate);
> +
> + /* Should we round up ? */
> + if (flags & CLK_MESON_MPLL_ROUND_CLOSEST
> + && rem > (requested_rate / 2)) {
> + frac = (frac + 1) % SDM_DEN;
> + if (frac == 0)
> + div += 1;
> + }
>
> if (div < N2_MIN) {
> *n2 = N2_MIN;
> @@ -102,7 +115,7 @@ static void params_from_rate(unsigned long requested_rate,
> *sdm = SDM_DEN - 1;
> } else {
> *n2 = div;
> - *sdm = DIV_ROUND_UP_ULL((u64)rem * SDM_DEN, requested_rate);
> + *sdm = frac;
> }
> }
>
> @@ -125,9 +138,11 @@ static long mpll_round_rate(struct clk_hw *hw,
> unsigned long rate,
> unsigned long *parent_rate)
> {
> + struct clk_regmap *clk = to_clk_regmap(hw);
> + struct meson_clk_mpll_data *mpll = meson_clk_mpll_data(clk);
> unsigned int sdm, n2;
>
> - params_from_rate(rate, *parent_rate, &sdm, &n2);
> + params_from_rate(rate, *parent_rate, &sdm, &n2, mpll->flags);
> return rate_from_params(*parent_rate, sdm, n2);
> }
>
> @@ -140,7 +155,7 @@ static int mpll_set_rate(struct clk_hw *hw,
> unsigned int sdm, n2;
> unsigned long flags = 0;
>
> - params_from_rate(rate, parent_rate, &sdm, &n2);
> + params_from_rate(rate, parent_rate, &sdm, &n2, mpll->flags);
>
> if (mpll->lock)
> spin_lock_irqsave(mpll->lock, flags);
> diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
> index 8fe73c4edca8..8cc265cd3d2b 100644
> --- a/drivers/clk/meson/clkc.h
> +++ b/drivers/clk/meson/clkc.h
> @@ -97,8 +97,11 @@ struct meson_clk_mpll_data {
> struct parm ssen;
> struct parm misc;
> spinlock_t *lock;
> + u8 flags;
> };
>
> +#define CLK_MESON_MPLL_ROUND_CLOSEST BIT(0)
> +
> struct meson_clk_audio_div_data {
> struct parm div;
> u8 flags;
>

Acked-by: Neil Armstrong <[email protected]>

2018-04-26 08:42:48

by Neil Armstrong

[permalink] [raw]
Subject: Re: [PATCH 2/2] clk: meson: axg: let mpll clocks round closest

On 20/04/2018 11:56, Jerome Brunet wrote:
> Let the mpll dividers achieve the closest rate possible, even if
> it means rounding the requested rate up.
>
> This is done to improve the accuracy of the rates provided by these
> plls to the audio subsystem
>
> Signed-off-by: Jerome Brunet <[email protected]>
> ---
> drivers/clk/meson/axg.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
> index 5f5d468c1efe..bd4dbc696b88 100644
> --- a/drivers/clk/meson/axg.c
> +++ b/drivers/clk/meson/axg.c
> @@ -461,6 +461,7 @@ static struct clk_regmap axg_mpll0_div = {
> .width = 1,
> },
> .lock = &meson_clk_lock,
> + .flags = CLK_MESON_MPLL_ROUND_CLOSEST,
> },
> .hw.init = &(struct clk_init_data){
> .name = "mpll0_div",
> @@ -507,6 +508,7 @@ static struct clk_regmap axg_mpll1_div = {
> .width = 1,
> },
> .lock = &meson_clk_lock,
> + .flags = CLK_MESON_MPLL_ROUND_CLOSEST,
> },
> .hw.init = &(struct clk_init_data){
> .name = "mpll1_div",
> @@ -553,6 +555,7 @@ static struct clk_regmap axg_mpll2_div = {
> .width = 1,
> },
> .lock = &meson_clk_lock,
> + .flags = CLK_MESON_MPLL_ROUND_CLOSEST,
> },
> .hw.init = &(struct clk_init_data){
> .name = "mpll2_div",
> @@ -599,6 +602,7 @@ static struct clk_regmap axg_mpll3_div = {
> .width = 1,
> },
> .lock = &meson_clk_lock,
> + .flags = CLK_MESON_MPLL_ROUND_CLOSEST,
> },
> .hw.init = &(struct clk_init_data){
> .name = "mpll3_div",
>

Acked-by: Neil Armstrong <[email protected]>

2018-04-27 09:35:42

by Jerome Brunet

[permalink] [raw]
Subject: Re: [PATCH 0/2] clk: meson: mpll: add round closest support

On Fri, 2018-04-20 at 11:56 +0200, Jerome Brunet wrote:
> ATM, the mpll driver can only round the requested rate down, even if
> rounding up would have provided a better approximation of the requested
> rate.
>
> This patchset adds a flag to enable rounding to the closest rate possible,
> even if it means rounding up.
>
> The flag is then enabled on the axg platform to improve the rates provided
> to the audio subsystem.
>
> Jerome Brunet (2):
> clk: meson: mpll: add round closest support
> clk: meson: axg: let mpll clocks round closest
>
> drivers/clk/meson/axg.c | 4 ++++
> drivers/clk/meson/clk-mpll.c | 25 ++++++++++++++++++++-----
> drivers/clk/meson/clkc.h | 3 +++
> 3 files changed, 27 insertions(+), 5 deletions(-)
>

Series applied with Neil's ack