diff mbox series

[v7,05/22] clk: Add functions to register CCF clock structs

Message ID 20200319205420.720815-6-seanga2@gmail.com
State Superseded
Delegated to: Andes
Headers show
Series riscv: Add Sipeed Maix support | expand

Commit Message

Sean Anderson March 19, 2020, 8:54 p.m. UTC
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@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(-)

Comments

Rick Chen March 30, 2020, 7:05 a.m. UTC | #1
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@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 mbox series

Patch

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,