[PATCH v2 3/6] clk: divider: add CLK_DIVIDER_HIWORD_MASK flag
Heiko Stübner
heiko at sntech.de
Fri Jun 7 08:31:22 EDT 2013
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?
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.
> + 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 :-)
Heiko
More information about the linux-arm-kernel
mailing list