On 4/5/24 21:56, Geert Uytterhoeven wrote: > 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) { And no need for an else after a return... >> + if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) >> + return ioread16be(divider->reg); >> + else and here. >> + return readw(divider->reg); >> + } else { >> + if (divider->flags & CLK_DIVIDER_BIG_ENDIAN) >> + return ioread32be(divider->reg); >> + else here too. >> + 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 > -- Damien Le Moal Western Digital Research