Re: [DO NOT MERGE v8 14/36] clk: Compatible with narrow registers

Stephen Boyd <[email protected]>
Newsgroups gmane.linux.kernel.clk,gmane.linux.ide,gmane.linux.drivers.devicetree,gmane.linux.kernel,gmane.linux.kernel.renesas-soc,gmane.comp.video.dri.devel,gmane.linux.kernel.pci,gmane.linux.serial,gmane.linux.ports.sh.devel
Message-ID <[email protected]>
Quoting Yoshinori Sato (2024-05-29 01:01:00)
> divider and gate only support 32-bit registers.
> Older hardware uses narrower registers, so I want to be able to handle
> 8-bit and 16-bit wide registers.
> 
> Seven clk_divider flags are used, and if I add flags for 8bit access and
> 16bit access, 8bit will not be enough, so I expanded it to u16.
> 
> Signed-off-by: Yoshinori Sato <[email protected]>
> ---
>  drivers/clk/clk-divider.c    | 41 +++++++++++++++++++++---------
>  drivers/clk/clk-gate.c       | 49 ++++++++++++++++++++++++++++++++----
>  include/linux/clk-provider.h | 20 ++++++++++++---
>  3 files changed, 89 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
> index a2c2b5203b0a..abafcbbb6578 100644
> --- a/drivers/clk/clk-divider.c
> +++ b/drivers/clk/clk-divider.c
> @@ -26,17 +26,34 @@
>   * parent - fixed parent.  No clk_set_parent support
>   */
>  
> -static inline u32 clk_div_readl(struct clk_divider *divider)
> -{
> +static inline u32 clk_div_read(struct clk_divider *divider)

Please don't change the name. The 'l' is for the return type, u32, which
is not changed.

> +{
> +       if (divider->flags & CLK_DIVIDER_REG_8BIT)
> +               return readb(divider->reg);
> +       if (divider->flags & CLK_DIVIDER_REG_16BIT) {
> +               if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) {
> +                       return ioread16be(divider->reg);
> +               } else {
> +                       return readw(divider->reg);
> +               }
> +       }
>         if (divider->flags & CLK_DIVIDER_BIG_ENDIAN)
>                 return ioread32be(divider->reg);
>  
>         return readl(divider->reg);
>  }
>  
> -static inline void clk_div_writel(struct clk_divider *divider, u32 val)
> +static inline void clk_div_write(struct clk_divider *divider, u32 val)

Same comment.

>  {
> -       if (divider->flags & CLK_DIVIDER_BIG_ENDIAN)
> +       if (divider->flags & CLK_DIVIDER_REG_8BIT)
> +               writeb(val, divider->reg);
> +       else if (divider->flags & CLK_DIVIDER_REG_16BIT) {
> +               if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) {
> +                       iowrite16be(val, divider->reg);
> +               } else {
> +                       writew(val, divider->reg);
> +               }
> +       } else if (divider->flags & CLK_DIVIDER_BIG_ENDIAN)
>                 iowrite32be(val, divider->reg);
>         else
>                 writel(val, divider->reg);
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 4a537260f655..25f61bd5b952 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -508,6 +508,10 @@ void of_fixed_clk_setup(struct device_node *np);
>   * CLK_GATE_BIG_ENDIAN - by default little endian register accesses are used for
>   *     the gate register.  Setting this flag makes the register accesses big
>   *     endian.
> + * CLK_GATE_REG_8BIT - by default 32bit register accesses are used for
> + *     the gate register.  Setting this flag makes the register accesses 8bit.
> + * CLK_GATE_REG_16BIT - by default 32bit register accesses are used for
> + *     the gate register.  Setting this flag makes the register accesses 16bit.
>   */
>  struct clk_gate {
>         struct clk_hw hw;
> @@ -522,6 +526,8 @@ struct clk_gate {
>  #define CLK_GATE_SET_TO_DISABLE                BIT(0)
>  #define CLK_GATE_HIWORD_MASK           BIT(1)
>  #define CLK_GATE_BIG_ENDIAN            BIT(2)
> +#define CLK_GATE_REG_8BIT              BIT(3)
> +#define CLK_GATE_REG_16BIT             BIT(4)

Please add kunit tests for the gate at least.

>  
>  extern const struct clk_ops clk_gate_ops;
>  struct clk_hw *__clk_hw_register_gate(struct device *dev,
> @@ -675,13 +681,17 @@ struct clk_div_table {
>   * CLK_DIVIDER_BIG_ENDIAN - By default little endian register accesses are used
>   *     for the divider register.  Setting this flag makes the register accesses
>   *     big endian.
> + * CLK_DIVIDER_REG_8BIT - by default 32bit register accesses are used for
> + *     the gate register.  Setting this flag makes the register accesses 8bit.
> + * CLK_DIVIDER_REG_16BIT - by default 32bit register accesses are used for
> + *     the gate register.  Setting this flag makes the register accesses 16bit.
>   */
>  struct clk_divider {
>         struct clk_hw   hw;
>         void __iomem    *reg;
>         u8              shift;
>         u8              width;
> -       u8              flags;
> +       u16             flags;
>         const struct clk_div_table      *table;
>         spinlock_t      *lock;
>  };
> @@ -697,6 +707,8 @@ struct clk_divider {
>  #define CLK_DIVIDER_READ_ONLY          BIT(5)
>  #define CLK_DIVIDER_MAX_AT_ZERO                BIT(6)
>  #define CLK_DIVIDER_BIG_ENDIAN         BIT(7)
> +#define CLK_DIVIDER_REG_8BIT           BIT(8)
> +#define CLK_DIVIDER_REG_16BIT          BIT(9)
>  
>  extern const struct clk_ops clk_divider_ops;
>  extern const struct clk_ops clk_divider_ro_ops;
> @@ -726,18 +738,18 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev,
>                 struct device_node *np, const char *name,
>                 const char *parent_name, const struct clk_hw *parent_hw,
>                 const struct clk_parent_data *parent_data, unsigned long flags,
> -               void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
> +               void __iomem *reg, u8 shift, u8 width, u16 clk_divider_flags,

Let's just make this unsigned long for the flags. We don't need to
specify a strict size like this for the callers.

>                 const struct clk_div_table *table, spinlock_t *lock);
>  struct clk_hw *__devm_clk_hw_register_divider(struct device *dev,
>                 struct device_node *np, const char *name,
>                 const char *parent_name, const struct clk_hw *parent_hw,
>                 const struct clk_parent_data *parent_data, unsigned long flags,
> -               void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
> +               void __iomem *reg, u8 shift, u8 width, u16 clk_divider_flags,

Same here.

>                 const struct clk_div_table *table, spinlock_t *lock);
>  struct clk *clk_register_divider_table(struct device *dev, const char *name,
>                 const char *parent_name, unsigned long flags,
>                 void __iomem *reg, u8 shift, u8 width,
> -               u8 clk_divider_flags, const struct clk_div_table *table,
> +               u16 clk_divider_flags, const struct clk_div_table *table,

Same here. Preferably do that in another patch too.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.