[PATCH v2 3/6] clk: divider: add CLK_DIVIDER_HIWORD_MASK flag
Heiko Stübner
heiko at sntech.de
Sat Jun 8 05:20:27 EDT 2013
Am Samstag, 8. Juni 2013, 05:17:16 schrieb Haojian Zhuang:
> On 7 June 2013 20:31, Heiko Stübner <heiko at sntech.de> wrote:
> > Hi Haojian,
> >
> > as Linus suggested, a bit of commentary for your side :-)
> >
> > The same also applies to the similar changes to the mux clock.
> >
> > Interestingly the gates on the hisilicon follow another paradigm
> > altogether, where on the Rockchip they also use this mask-mechanism.
> >
> > Am Dienstag, 4. Juni 2013, 17:05:14 schrieb Haojian Zhuang:
> >> In Hisilicon Hi3620 clock divider register, 16-bit HIWORD is mask field.
> >> Support the HIWORD mask to reuse clock divider driver.
> >>
> >> Signed-off-by: Haojian Zhuang <haojian.zhuang at linaro.org>
> >> ---
> >>
> >> drivers/clk/clk-divider.c | 6 ++++++
> >> include/linux/clk-provider.h | 2 ++
> >> 2 files changed, 8 insertions(+)
> >>
> >> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> >> index 6d96741..4c344b4 100644
> >> --- a/drivers/clk/clk-divider.c
> >> +++ b/drivers/clk/clk-divider.c
> >> @@ -220,6 +220,12 @@ static int clk_divider_set_rate(struct clk_hw *hw,
> >> unsigned long rate, val = readl(divider->reg);
> >>
> >> val &= ~(div_mask(divider) << divider->shift);
> >
> > Do you really need to read the register value on the HiSilicon before
> > changing it?
>
> Because there's a mask field in the register, it could work without
> reading. My purpose is only to do less change in common code.
>
> > On the Rockchip side, the mask is used just for just this, to indicate
> > the bits that are set in the lower part, so there there really is no
> > separate read necessary when changing bits.
> >
> >> val |= value << divider->shift;
> >>
> >> + if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
> >> + if (divider->width + divider->shift > 16)
> >> + pr_warn("divider value exceeds LOWORD field\n");
> >
> > This can be checked in the clock setup. If shift and mask are exceeding
> > the low word there is something seriously wrong with the setup data and
> > the clock shouldn't be created at all. This also saves the conditional
> > on every set operation.
>
> OK.
>
> >> + else
> >> + val |= div_mask(divider) << (divider->shift + 16);
> >> + }
> >>
> >> writel(val, divider->reg);
> >>
> >> if (divider->lock)
> >>
> >> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> >> index 6ba32bc..dbb9bd9 100644
> >> --- a/include/linux/clk-provider.h
> >> +++ b/include/linux/clk-provider.h
> >> @@ -257,6 +257,7 @@ struct clk_div_table {
> >>
> >> * Some hardware implementations gracefully handle this case and
> >> allow a * zero divisor by not modifying their input clock
> >> * (divide by one / bypass).
> >>
> >> + * CLK_DIVIDER_HIWORD_MASK - register contains high 16-bit as mask
> >> field
> >>
> >> */
> >>
> >> struct clk_divider {
> >>
> >> struct clk_hw hw;
> >>
> >> @@ -271,6 +272,7 @@ struct clk_divider {
> >>
> >> #define CLK_DIVIDER_ONE_BASED BIT(0)
> >> #define CLK_DIVIDER_POWER_OF_TWO BIT(1)
> >> #define CLK_DIVIDER_ALLOW_ZERO BIT(2)
> >>
> >> +#define CLK_DIVIDER_HIWORD_MASK BIT(3)
> >
> > I like your naming a lot better than mine :-)
>
> OK. How about I sent the next version. And you can base on mine version.
> I'll append your comments & logic in my version. And I'll split your
> patches into three that are gate, mux and divider.
sure, go ahead, but would say without the unecessary read we talked about
above.
Heiko
More information about the linux-arm-kernel
mailing list