Hi Sato-san, On Thu, Apr 4, 2024 at 7:15 AM Yoshinori Sato <ysato@xxxxxxxxxxxxxxxxxxxx> wrote: > 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 <ysato@xxxxxxxxxxxxxxxxxxxx> Thanks for the update! > --- a/drivers/clk/clk-divider.c > +++ b/drivers/clk/clk-divider.c > @@ -26,20 +26,38 @@ > * parent - fixed parent. No clk_set_parent support > */ > > -static inline u32 clk_div_readl(struct clk_divider *divider) > -{ > - if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) > - return ioread32be(divider->reg); > - > - return readl(divider->reg); > +static inline u32 clk_div_read(struct clk_divider *divider) > +{ > + if (divider->flags & CLK_DIVIDER_REG_8BIT) When you need curly braces in one branch of an if/else statement, please use curly braces in all branches (everywhere). > + return readb(divider->reg); > + else if (divider->flags & CLK_DIVIDER_REG_16BIT) { > + if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) > + return ioread16be(divider->reg); > + else > + return readw(divider->reg); > + } else { > + if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) > + return ioread32be(divider->reg); > + else > + return readl(divider->reg); > + } > } > --- a/drivers/clk/clk-gate.c > +++ b/drivers/clk/clk-gate.c > @@ -137,12 +155,30 @@ struct clk_hw *__clk_hw_register_gate(struct device *dev, > struct clk_init_data init = {}; > int ret = -EINVAL; > > + /* validate register size option and bit_idx */ > if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { > if (bit_idx > 15) { > pr_err("gate bit exceeds LOWORD field\n"); > return ERR_PTR(-EINVAL); > } > } > + if (clk_gate_flags & CLK_GATE_REG_16BIT) { > + if (bit_idx > 15) { > + pr_err("gate bit exceeds 16 bits\n"); > + return ERR_PTR(-EINVAL); > + } > + } > + if (clk_gate_flags & CLK_GATE_REG_8BIT) { > + if (bit_idx > 7) { > + pr_err("gate bit exceeds 8 bits\n"); > + return ERR_PTR(-EINVAL); > + } > + } > + if ((clk_gate_flags & CLK_GATE_HIWORD_MASK) && If you use parentheses around "a & b" here... > + clk_gate_flags & (CLK_GATE_REG_8BIT | CLK_GATE_REG_16BIT)) { please add parentheses here, too. > + pr_err("HIWORD_MASK required 32-bit register\n"); > + return ERR_PTR(-EINVAL); > + } > > /* allocate the gate */ > gate = kzalloc(sizeof(*gate), GFP_KERNEL); > diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h > index 4a537260f655..eaa6ff1d0b2e 100644 > --- a/include/linux/clk-provider.h > +++ b/include/linux/clk-provider.h > @@ -508,12 +508,16 @@ 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; > void __iomem *reg; > u8 bit_idx; > - u8 flags; > + u32 flags; (from my comments on v6) There is no need to increase the size of the flags field for the gate clock. > spinlock_t *lock; > }; > > @@ -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; > }; > @@ -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, u32 clk_divider_flags, "u16 clk_divider_flags", to match clk_divider.flags. > 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, u32 clk_divider_flags, Likewise. > 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, > + u32 clk_divider_flags, const struct clk_div_table *table, Likewise. > spinlock_t *lock); > /** > * clk_register_divider - register a divider clock with the clock framework Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@xxxxxxxxxxxxxx In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds