Message ID | 20200319205420.720815-6-seanga2@gmail.com |
---|---|
State | New |
Headers | show |
Series | riscv: Add Sipeed Maix support | expand |
Hi Peng and Lukasz > This patch adds alternate versions of the clk_*_register functions for use > with statically-allocated struct clks. This allows drivers to define clocks > at compile-time and register them at run-time without malloc-ing. This > increases the size of the binary, but should not affect ram usage (since > the clocks now no longer live on the heap). > > Signed-off-by: Sean Anderson <seanga2 at gmail.com> > --- > > Changes in v5: > - New > > drivers/clk/clk-composite.c | 103 +++++++++++++++++++---------------- > drivers/clk/clk-divider.c | 56 +++++++++---------- > drivers/clk/clk-gate.c | 38 ++++++++----- > include/linux/clk-provider.h | 9 +++ > 4 files changed, 112 insertions(+), 94 deletions(-) > Do you have any comments about this patch ? Thanks Rick > diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c > index 819bfca2fc..b328c4e5a5 100644 > --- a/drivers/clk/clk-composite.c > +++ b/drivers/clk/clk-composite.c > @@ -95,6 +95,51 @@ static int clk_composite_disable(struct clk *clk) > return 0; > } > > +struct clk *clk_register_composite_struct(const char *name, > + const char * const *parent_names, > + int num_parents, > + struct clk_composite *composite) > +{ > + int ret; > + struct clk *clk; > + > + if (!num_parents || (num_parents != 1 && !composite->mux)) > + return ERR_PTR(-EINVAL); > + > + if (composite->mux && composite->mux_ops) > + composite->mux->data = (ulong)composite; > + > + if (composite->rate && composite->rate_ops) { > + if (!composite->rate_ops->get_rate) > + return ERR_PTR(-EINVAL); > + > + composite->rate->data = (ulong)composite; > + } > + > + if (composite->gate && composite->gate_ops) { > + if (!composite->gate_ops->enable || > + !composite->gate_ops->disable) > + return ERR_PTR(-EINVAL); > + > + composite->gate->data = (ulong)composite; > + } > + > + clk = &composite->clk; > + ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, name, > + parent_names[clk_composite_get_parent(clk)]); > + if (ret) > + clk = ERR_PTR(ret); > + > + if (composite->mux) > + composite->mux->dev = clk->dev; > + if (composite->rate) > + composite->rate->dev = clk->dev; > + if (composite->gate) > + composite->gate->dev = clk->dev; > + > + return clk; > +} > + > struct clk *clk_register_composite(struct device *dev, const char *name, > const char * const *parent_names, > int num_parents, struct clk *mux, > @@ -107,62 +152,24 @@ struct clk *clk_register_composite(struct device *dev, const char *name, > { > struct clk *clk; > struct clk_composite *composite; > - int ret; > - > - if (!num_parents || (num_parents != 1 && !mux)) > - return ERR_PTR(-EINVAL); > > composite = kzalloc(sizeof(*composite), GFP_KERNEL); > if (!composite) > return ERR_PTR(-ENOMEM); > > - if (mux && mux_ops) { > - composite->mux = mux; > - composite->mux_ops = mux_ops; > - mux->data = (ulong)composite; > - } > + composite->mux = mux; > + composite->mux_ops = mux_ops; > > - if (rate && rate_ops) { > - if (!rate_ops->get_rate) { > - clk = ERR_PTR(-EINVAL); > - goto err; > - } > + composite->rate = rate; > + composite->rate_ops = rate_ops; > > - composite->rate = rate; > - composite->rate_ops = rate_ops; > - rate->data = (ulong)composite; > - } > + composite->gate = gate; > + composite->gate_ops = gate_ops; > > - if (gate && gate_ops) { > - if (!gate_ops->enable || !gate_ops->disable) { > - clk = ERR_PTR(-EINVAL); > - goto err; > - } > - > - composite->gate = gate; > - composite->gate_ops = gate_ops; > - gate->data = (ulong)composite; > - } > - > - clk = &composite->clk; > - ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, name, > - parent_names[clk_composite_get_parent(clk)]); > - if (ret) { > - clk = ERR_PTR(ret); > - goto err; > - } > - > - if (composite->mux) > - composite->mux->dev = clk->dev; > - if (composite->rate) > - composite->rate->dev = clk->dev; > - if (composite->gate) > - composite->gate->dev = clk->dev; > - > - return clk; > - > -err: > - kfree(composite); > + clk = clk_register_composite_struct(name, parent_names, num_parents, > + composite); > + if (IS_ERR(clk)) > + kfree(composite); > return clk; > } > > diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c > index 5fe1c3941f..747504d0a0 100644 > --- a/drivers/clk/clk-divider.c > +++ b/drivers/clk/clk-divider.c > @@ -178,22 +178,37 @@ const struct clk_ops clk_divider_ops = { > .set_rate = clk_divider_set_rate, > }; > > -static struct clk *_register_divider(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) > +struct clk *clk_register_divider_struct(const char *name, > + const char *parent_name, > + struct clk_divider *div) > { > - struct clk_divider *div; > - struct clk *clk; > int ret; > + struct clk *clk; > > - if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) { > - if (width + shift > 16) { > + if (div->flags & CLK_DIVIDER_HIWORD_MASK) { > + if (div->width + div->shift > 16) { > pr_warn("divider value exceeds LOWORD field\n"); > return ERR_PTR(-EINVAL); > } > } > > + /* register the clock */ > + clk = &div->clk; > + > + ret = clk_register(clk, UBOOT_DM_CLK_CCF_DIVIDER, name, parent_name); > + if (ret) > + return ERR_PTR(ret); > + return clk; > +} > + > +struct clk *clk_register_divider(struct device *dev, const char *name, > + const char *parent_name, unsigned long flags, > + void __iomem *reg, u8 shift, u8 width, > + u8 clk_divider_flags) > +{ > + struct clk_divider *div; > + struct clk *clk; > + > /* allocate the divider */ > div = kzalloc(sizeof(*div), GFP_KERNEL); > if (!div) > @@ -204,34 +219,13 @@ static struct clk *_register_divider(struct device *dev, const char *name, > div->shift = shift; > div->width = width; > div->flags = clk_divider_flags; > - div->table = table; > #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF) > div->io_divider_val = *(u32 *)reg; > #endif > > - /* register the clock */ > - clk = &div->clk; > - > - ret = clk_register(clk, UBOOT_DM_CLK_CCF_DIVIDER, name, parent_name); > - if (ret) { > - kfree(div); > - return ERR_PTR(ret); > - } > - > - return clk; > -} > - > -struct clk *clk_register_divider(struct device *dev, const char *name, > - const char *parent_name, unsigned long flags, > - void __iomem *reg, u8 shift, u8 width, > - u8 clk_divider_flags) > -{ > - struct clk *clk; > - > - clk = _register_divider(dev, name, parent_name, flags, reg, shift, > - width, clk_divider_flags, NULL); > + clk = clk_register_divider_struct(name, parent_name, div); > if (IS_ERR(clk)) > - return ERR_CAST(clk); > + kfree(div); > return clk; > } > > diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c > index b5827dced0..82445d2ccb 100644 > --- a/drivers/clk/clk-gate.c > +++ b/drivers/clk/clk-gate.c > @@ -111,6 +111,27 @@ const struct clk_ops clk_gate_ops = { > .get_rate = clk_generic_get_rate, > }; > > +struct clk *clk_register_gate_struct(const char *name, const char *parent_name, > + struct clk_gate *gate) > +{ > + int ret; > + struct clk *clk; > + > + if (gate->flags & CLK_GATE_HIWORD_MASK) { > + if (gate->bit_idx > 15) { > + pr_err("gate bit exceeds LOWORD field\n"); > + return ERR_PTR(-EINVAL); > + } > + } > + > + clk = &gate->clk; > + > + ret = clk_register(clk, UBOOT_DM_CLK_GATE, name, parent_name); > + if (ret) > + return ERR_PTR(ret); > + return clk; > +} > + > struct clk *clk_register_gate(struct device *dev, const char *name, > const char *parent_name, unsigned long flags, > void __iomem *reg, u8 bit_idx, > @@ -118,14 +139,6 @@ struct clk *clk_register_gate(struct device *dev, const char *name, > { > struct clk_gate *gate; > struct clk *clk; > - int ret; > - > - if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { > - if (bit_idx > 15) { > - pr_err("gate bit exceeds LOWORD field\n"); > - return ERR_PTR(-EINVAL); > - } > - } > > /* allocate the gate */ > gate = kzalloc(sizeof(*gate), GFP_KERNEL); > @@ -140,14 +153,9 @@ struct clk *clk_register_gate(struct device *dev, const char *name, > gate->io_gate_val = *(u32 *)reg; > #endif > > - clk = &gate->clk; > - > - ret = clk_register(clk, UBOOT_DM_CLK_GATE, name, parent_name); > - if (ret) { > + clk = clk_register_gate_struct(name, parent_name, gate); > + if (IS_ERR(clk)) > kfree(gate); > - return ERR_PTR(ret); > - } > - > return clk; > } > > diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h > index 8a20743ad8..8bf8dca0a3 100644 > --- a/include/linux/clk-provider.h > +++ b/include/linux/clk-provider.h > @@ -95,6 +95,8 @@ struct clk *clk_register_gate(struct device *dev, const char *name, > const char *parent_name, unsigned long flags, > void __iomem *reg, u8 bit_idx, > u8 clk_gate_flags, spinlock_t *lock); > +struct clk *clk_register_gate_struct(const char *name, const char *parent_name, > + struct clk_gate *gate); > > struct clk_div_table { > unsigned int val; > @@ -166,6 +168,10 @@ struct clk *clk_register_composite(struct device *dev, const char *name, > struct clk *rate_clk, const struct clk_ops *rate_ops, > struct clk *gate_clk, const struct clk_ops *gate_ops, > unsigned long flags); > +struct clk *clk_register_composite_struct(const char *name, > + const char * const *parent_names, > + int num_parents, > + struct clk_composite *composite); > > int clk_register(struct clk *clk, const char *drv_name, const char *name, > const char *parent_name); > @@ -178,6 +184,9 @@ struct clk *clk_register_divider(struct device *dev, const char *name, > const char *parent_name, unsigned long flags, > void __iomem *reg, u8 shift, u8 width, > u8 clk_divider_flags); > +struct clk *clk_register_divider_struct(const char *name, > + const char *parent_name, > + struct clk_divider *div); > > struct clk *clk_register_mux(struct device *dev, const char *name, > const char * const *parent_names, u8 num_parents, > -- > 2.25.1 >
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index 819bfca2fc..b328c4e5a5 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -95,6 +95,51 @@ static int clk_composite_disable(struct clk *clk) return 0; } +struct clk *clk_register_composite_struct(const char *name, + const char * const *parent_names, + int num_parents, + struct clk_composite *composite) +{ + int ret; + struct clk *clk; + + if (!num_parents || (num_parents != 1 && !composite->mux)) + return ERR_PTR(-EINVAL); + + if (composite->mux && composite->mux_ops) + composite->mux->data = (ulong)composite; + + if (composite->rate && composite->rate_ops) { + if (!composite->rate_ops->get_rate) + return ERR_PTR(-EINVAL); + + composite->rate->data = (ulong)composite; + } + + if (composite->gate && composite->gate_ops) { + if (!composite->gate_ops->enable || + !composite->gate_ops->disable) + return ERR_PTR(-EINVAL); + + composite->gate->data = (ulong)composite; + } + + clk = &composite->clk; + ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, name, + parent_names[clk_composite_get_parent(clk)]); + if (ret) + clk = ERR_PTR(ret); + + if (composite->mux) + composite->mux->dev = clk->dev; + if (composite->rate) + composite->rate->dev = clk->dev; + if (composite->gate) + composite->gate->dev = clk->dev; + + return clk; +} + struct clk *clk_register_composite(struct device *dev, const char *name, const char * const *parent_names, int num_parents, struct clk *mux, @@ -107,62 +152,24 @@ struct clk *clk_register_composite(struct device *dev, const char *name, { struct clk *clk; struct clk_composite *composite; - int ret; - - if (!num_parents || (num_parents != 1 && !mux)) - return ERR_PTR(-EINVAL); composite = kzalloc(sizeof(*composite), GFP_KERNEL); if (!composite) return ERR_PTR(-ENOMEM); - if (mux && mux_ops) { - composite->mux = mux; - composite->mux_ops = mux_ops; - mux->data = (ulong)composite; - } + composite->mux = mux; + composite->mux_ops = mux_ops; - if (rate && rate_ops) { - if (!rate_ops->get_rate) { - clk = ERR_PTR(-EINVAL); - goto err; - } + composite->rate = rate; + composite->rate_ops = rate_ops; - composite->rate = rate; - composite->rate_ops = rate_ops; - rate->data = (ulong)composite; - } + composite->gate = gate; + composite->gate_ops = gate_ops; - if (gate && gate_ops) { - if (!gate_ops->enable || !gate_ops->disable) { - clk = ERR_PTR(-EINVAL); - goto err; - } - - composite->gate = gate; - composite->gate_ops = gate_ops; - gate->data = (ulong)composite; - } - - clk = &composite->clk; - ret = clk_register(clk, UBOOT_DM_CLK_COMPOSITE, name, - parent_names[clk_composite_get_parent(clk)]); - if (ret) { - clk = ERR_PTR(ret); - goto err; - } - - if (composite->mux) - composite->mux->dev = clk->dev; - if (composite->rate) - composite->rate->dev = clk->dev; - if (composite->gate) - composite->gate->dev = clk->dev; - - return clk; - -err: - kfree(composite); + clk = clk_register_composite_struct(name, parent_names, num_parents, + composite); + if (IS_ERR(clk)) + kfree(composite); return clk; } diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index 5fe1c3941f..747504d0a0 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -178,22 +178,37 @@ const struct clk_ops clk_divider_ops = { .set_rate = clk_divider_set_rate, }; -static struct clk *_register_divider(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) +struct clk *clk_register_divider_struct(const char *name, + const char *parent_name, + struct clk_divider *div) { - struct clk_divider *div; - struct clk *clk; int ret; + struct clk *clk; - if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) { - if (width + shift > 16) { + if (div->flags & CLK_DIVIDER_HIWORD_MASK) { + if (div->width + div->shift > 16) { pr_warn("divider value exceeds LOWORD field\n"); return ERR_PTR(-EINVAL); } } + /* register the clock */ + clk = &div->clk; + + ret = clk_register(clk, UBOOT_DM_CLK_CCF_DIVIDER, name, parent_name); + if (ret) + return ERR_PTR(ret); + return clk; +} + +struct clk *clk_register_divider(struct device *dev, const char *name, + const char *parent_name, unsigned long flags, + void __iomem *reg, u8 shift, u8 width, + u8 clk_divider_flags) +{ + struct clk_divider *div; + struct clk *clk; + /* allocate the divider */ div = kzalloc(sizeof(*div), GFP_KERNEL); if (!div) @@ -204,34 +219,13 @@ static struct clk *_register_divider(struct device *dev, const char *name, div->shift = shift; div->width = width; div->flags = clk_divider_flags; - div->table = table; #if CONFIG_IS_ENABLED(SANDBOX_CLK_CCF) div->io_divider_val = *(u32 *)reg; #endif - /* register the clock */ - clk = &div->clk; - - ret = clk_register(clk, UBOOT_DM_CLK_CCF_DIVIDER, name, parent_name); - if (ret) { - kfree(div); - return ERR_PTR(ret); - } - - return clk; -} - -struct clk *clk_register_divider(struct device *dev, const char *name, - const char *parent_name, unsigned long flags, - void __iomem *reg, u8 shift, u8 width, - u8 clk_divider_flags) -{ - struct clk *clk; - - clk = _register_divider(dev, name, parent_name, flags, reg, shift, - width, clk_divider_flags, NULL); + clk = clk_register_divider_struct(name, parent_name, div); if (IS_ERR(clk)) - return ERR_CAST(clk); + kfree(div); return clk; } diff --git a/drivers/clk/clk-gate.c b/drivers/clk/clk-gate.c index b5827dced0..82445d2ccb 100644 --- a/drivers/clk/clk-gate.c +++ b/drivers/clk/clk-gate.c @@ -111,6 +111,27 @@ const struct clk_ops clk_gate_ops = { .get_rate = clk_generic_get_rate, }; +struct clk *clk_register_gate_struct(const char *name, const char *parent_name, + struct clk_gate *gate) +{ + int ret; + struct clk *clk; + + if (gate->flags & CLK_GATE_HIWORD_MASK) { + if (gate->bit_idx > 15) { + pr_err("gate bit exceeds LOWORD field\n"); + return ERR_PTR(-EINVAL); + } + } + + clk = &gate->clk; + + ret = clk_register(clk, UBOOT_DM_CLK_GATE, name, parent_name); + if (ret) + return ERR_PTR(ret); + return clk; +} + struct clk *clk_register_gate(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 bit_idx, @@ -118,14 +139,6 @@ struct clk *clk_register_gate(struct device *dev, const char *name, { struct clk_gate *gate; struct clk *clk; - int ret; - - if (clk_gate_flags & CLK_GATE_HIWORD_MASK) { - if (bit_idx > 15) { - pr_err("gate bit exceeds LOWORD field\n"); - return ERR_PTR(-EINVAL); - } - } /* allocate the gate */ gate = kzalloc(sizeof(*gate), GFP_KERNEL); @@ -140,14 +153,9 @@ struct clk *clk_register_gate(struct device *dev, const char *name, gate->io_gate_val = *(u32 *)reg; #endif - clk = &gate->clk; - - ret = clk_register(clk, UBOOT_DM_CLK_GATE, name, parent_name); - if (ret) { + clk = clk_register_gate_struct(name, parent_name, gate); + if (IS_ERR(clk)) kfree(gate); - return ERR_PTR(ret); - } - return clk; } diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 8a20743ad8..8bf8dca0a3 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -95,6 +95,8 @@ struct clk *clk_register_gate(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 bit_idx, u8 clk_gate_flags, spinlock_t *lock); +struct clk *clk_register_gate_struct(const char *name, const char *parent_name, + struct clk_gate *gate); struct clk_div_table { unsigned int val; @@ -166,6 +168,10 @@ struct clk *clk_register_composite(struct device *dev, const char *name, struct clk *rate_clk, const struct clk_ops *rate_ops, struct clk *gate_clk, const struct clk_ops *gate_ops, unsigned long flags); +struct clk *clk_register_composite_struct(const char *name, + const char * const *parent_names, + int num_parents, + struct clk_composite *composite); int clk_register(struct clk *clk, const char *drv_name, const char *name, const char *parent_name); @@ -178,6 +184,9 @@ struct clk *clk_register_divider(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags); +struct clk *clk_register_divider_struct(const char *name, + const char *parent_name, + struct clk_divider *div); struct clk *clk_register_mux(struct device *dev, const char *name, const char * const *parent_names, u8 num_parents,
This patch adds alternate versions of the clk_*_register functions for use with statically-allocated struct clks. This allows drivers to define clocks at compile-time and register them at run-time without malloc-ing. This increases the size of the binary, but should not affect ram usage (since the clocks now no longer live on the heap). Signed-off-by: Sean Anderson <seanga2 at gmail.com> --- Changes in v5: - New drivers/clk/clk-composite.c | 103 +++++++++++++++++++---------------- drivers/clk/clk-divider.c | 56 +++++++++---------- drivers/clk/clk-gate.c | 38 ++++++++----- include/linux/clk-provider.h | 9 +++ 4 files changed, 112 insertions(+), 94 deletions(-)