diff mbox

[3/5] clk: imx: add CPU clock type

Message ID 1411143381-10516-4-git-send-email-l.stach@pengutronix.de (mailing list archive)
State Changes Requested, archived
Headers show

Commit Message

Lucas Stach Sept. 19, 2014, 4:16 p.m. UTC
From: Lucas Stach <dev@lynxeye.de>

This implements a virtual clock used to abstract away
all the steps needed in order to change the ARM clock,
so we don't have to push all this clock handling into
the cpufreq driver.

While it will be used for i.MX53 at first it is generic
enough to be used on i.MX6 later on.

Signed-off-by: Lucas Stach <dev@lynxeye.de>
---
 arch/arm/mach-imx/Makefile  |   2 +-
 arch/arm/mach-imx/clk-cpu.c | 104 ++++++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-imx/clk.h     |   4 ++
 3 files changed, 109 insertions(+), 1 deletion(-)
 create mode 100644 arch/arm/mach-imx/clk-cpu.c

Comments

Shawn Guo Sept. 26, 2014, 2:59 a.m. UTC | #1
On Fri, Sep 19, 2014 at 06:16:19PM +0200, Lucas Stach wrote:
> From: Lucas Stach <dev@lynxeye.de>
> 
> This implements a virtual clock used to abstract away
> all the steps needed in order to change the ARM clock,
> so we don't have to push all this clock handling into
> the cpufreq driver.
> 
> While it will be used for i.MX53 at first it is generic
> enough to be used on i.MX6 later on.
> 
> Signed-off-by: Lucas Stach <dev@lynxeye.de>

Is this intentional to use a different email address than your usual
one?

> ---
>  arch/arm/mach-imx/Makefile  |   2 +-
>  arch/arm/mach-imx/clk-cpu.c | 104 ++++++++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-imx/clk.h     |   4 ++
>  3 files changed, 109 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm/mach-imx/clk-cpu.c
> 
> diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
> index ac88599ca080..4d6071351f4f 100644
> --- a/arch/arm/mach-imx/Makefile
> +++ b/arch/arm/mach-imx/Makefile
> @@ -12,7 +12,7 @@ obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-
>  obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
>  
>  imx5-pm-$(CONFIG_PM) += pm-imx5.o
> -obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o $(imx5-pm-y)
> +obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o clk-cpu.o $(imx5-pm-y)
>  
>  obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
>  			    clk-pfd.o clk-busy.o clk.o \
> diff --git a/arch/arm/mach-imx/clk-cpu.c b/arch/arm/mach-imx/clk-cpu.c
> new file mode 100644
> index 000000000000..ffba96228d3b
> --- /dev/null
> +++ b/arch/arm/mach-imx/clk-cpu.c
> @@ -0,0 +1,104 @@
> +/*
> + * Copyright (c) 2014 Lucas Stach <l.stach@pengutronix.de>, Pengutronix
> + *
> + * The code contained herein is licensed under the GNU General Public
> + * License. You may obtain a copy of the GNU General Public License
> + * Version 2 or later at the following locations:
> + *
> + * http://www.opensource.org/licenses/gpl-license.html
> + * http://www.gnu.org/copyleft/gpl.html
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +
> +struct clk_cpu {
> +	struct clk_hw	hw;
> +	struct clk	*div, *mux, *pll, *step;

This is personal taste, so I'm not strong on this.  But I feel having
them on multiple lines makes the later addition/removal of struct clk
pointers a bit easier.

Other than these trivial comments, the patch looks good to me.

Shawn

> +};
--
To unsubscribe from this list: send the line "unsubscribe linux-pm" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Lucas Stach Sept. 26, 2014, 10:10 a.m. UTC | #2
Am Freitag, den 26.09.2014, 10:59 +0800 schrieb Shawn Guo:
> On Fri, Sep 19, 2014 at 06:16:19PM +0200, Lucas Stach wrote:
> > From: Lucas Stach <dev@lynxeye.de>
> > 
> > This implements a virtual clock used to abstract away
> > all the steps needed in order to change the ARM clock,
> > so we don't have to push all this clock handling into
> > the cpufreq driver.
> > 
> > While it will be used for i.MX53 at first it is generic
> > enough to be used on i.MX6 later on.
> > 
> > Signed-off-by: Lucas Stach <dev@lynxeye.de>
> 
> Is this intentional to use a different email address than your usual
> one?

Urgh no. That's a remnant from starting this code at home without
setting the proper git environment. Thanks for the hint.

> 
> > ---
> >  arch/arm/mach-imx/Makefile  |   2 +-
> >  arch/arm/mach-imx/clk-cpu.c | 104 ++++++++++++++++++++++++++++++++++++++++++++
> >  arch/arm/mach-imx/clk.h     |   4 ++
> >  3 files changed, 109 insertions(+), 1 deletion(-)
> >  create mode 100644 arch/arm/mach-imx/clk-cpu.c
> > 
> > diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
> > index ac88599ca080..4d6071351f4f 100644
> > --- a/arch/arm/mach-imx/Makefile
> > +++ b/arch/arm/mach-imx/Makefile
> > @@ -12,7 +12,7 @@ obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-
> >  obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
> >  
> >  imx5-pm-$(CONFIG_PM) += pm-imx5.o
> > -obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o $(imx5-pm-y)
> > +obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o clk-cpu.o $(imx5-pm-y)
> >  
> >  obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
> >  			    clk-pfd.o clk-busy.o clk.o \
> > diff --git a/arch/arm/mach-imx/clk-cpu.c b/arch/arm/mach-imx/clk-cpu.c
> > new file mode 100644
> > index 000000000000..ffba96228d3b
> > --- /dev/null
> > +++ b/arch/arm/mach-imx/clk-cpu.c
> > @@ -0,0 +1,104 @@
> > +/*
> > + * Copyright (c) 2014 Lucas Stach <l.stach@pengutronix.de>, Pengutronix
> > + *
> > + * The code contained herein is licensed under the GNU General Public
> > + * License. You may obtain a copy of the GNU General Public License
> > + * Version 2 or later at the following locations:
> > + *
> > + * http://www.opensource.org/licenses/gpl-license.html
> > + * http://www.gnu.org/copyleft/gpl.html
> > + */
> > +
> > +#include <linux/clk.h>
> > +#include <linux/clk-provider.h>
> > +#include <linux/slab.h>
> > +
> > +struct clk_cpu {
> > +	struct clk_hw	hw;
> > +	struct clk	*div, *mux, *pll, *step;
> 
> This is personal taste, so I'm not strong on this.  But I feel having
> them on multiple lines makes the later addition/removal of struct clk
> pointers a bit easier.
> 
> Other than these trivial comments, the patch looks good to me.
> 
> Shawn
> 
> > +};
> --
> To unsubscribe from this list: send the line "unsubscribe linux-pm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index ac88599ca080..4d6071351f4f 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -12,7 +12,7 @@  obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-
 obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
 
 imx5-pm-$(CONFIG_PM) += pm-imx5.o
-obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o $(imx5-pm-y)
+obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o clk-imx51-imx53.o clk-cpu.o $(imx5-pm-y)
 
 obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
 			    clk-pfd.o clk-busy.o clk.o \
diff --git a/arch/arm/mach-imx/clk-cpu.c b/arch/arm/mach-imx/clk-cpu.c
new file mode 100644
index 000000000000..ffba96228d3b
--- /dev/null
+++ b/arch/arm/mach-imx/clk-cpu.c
@@ -0,0 +1,104 @@ 
+/*
+ * Copyright (c) 2014 Lucas Stach <l.stach@pengutronix.de>, Pengutronix
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+
+struct clk_cpu {
+	struct clk_hw	hw;
+	struct clk	*div, *mux, *pll, *step;
+};
+
+static inline struct clk_cpu *to_clk_cpu(struct clk_hw *hw)
+{
+	return container_of(hw, struct clk_cpu, hw);
+}
+
+static unsigned long clk_cpu_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct clk_cpu *cpu = to_clk_cpu(hw);
+
+	return clk_get_rate(cpu->div);
+}
+
+static long clk_cpu_round_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long *prate)
+{
+	struct clk_cpu *cpu = to_clk_cpu(hw);
+
+	return clk_round_rate(cpu->pll, rate);
+}
+
+static int clk_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	struct clk_cpu *cpu = to_clk_cpu(hw);
+	int ret;
+
+	/* switch to PLL bypass clock */
+	ret = clk_set_parent(cpu->mux, cpu->step);
+	if (ret)
+		return ret;
+
+	/* reprogram PLL */
+	ret = clk_set_rate(cpu->pll, rate);
+	if (ret) {
+		clk_set_parent(cpu->mux, cpu->pll);
+		return ret;
+	}
+	/* switch back to PLL clock */
+	clk_set_parent(cpu->mux, cpu->pll);
+
+	/* Ensure the divider is what we expect */
+	clk_set_rate(cpu->div, rate);
+
+	return 0;
+}
+
+static const struct clk_ops clk_cpu_ops = {
+	.recalc_rate	= clk_cpu_recalc_rate,
+	.round_rate	= clk_cpu_round_rate,
+	.set_rate	= clk_cpu_set_rate,
+};
+
+struct clk *imx_clk_cpu(const char *name, const char *parent_name,
+		struct clk *div, struct clk *mux, struct clk *pll,
+		struct clk *step)
+{
+	struct clk_cpu *cpu;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	cpu = kzalloc(sizeof(*cpu), GFP_KERNEL);
+	if (!cpu)
+		return ERR_PTR(-ENOMEM);
+
+	cpu->div = div;
+	cpu->mux = mux;
+	cpu->pll = pll;
+	cpu->step = step;
+
+	init.name = name;
+	init.ops = &clk_cpu_ops;
+	init.flags = 0;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	cpu->hw.init = &init;
+
+	clk = clk_register(NULL, &cpu->hw);
+	if (IS_ERR(clk))
+		kfree(cpu);
+
+	return clk;
+}
diff --git a/arch/arm/mach-imx/clk.h b/arch/arm/mach-imx/clk.h
index d5ba76fee115..5de8b53ec208 100644
--- a/arch/arm/mach-imx/clk.h
+++ b/arch/arm/mach-imx/clk.h
@@ -128,4 +128,8 @@  static inline struct clk *imx_clk_fixed_factor(const char *name,
 			CLK_SET_RATE_PARENT, mult, div);
 }
 
+struct clk *imx_clk_cpu(const char *name, const char *parent_name,
+		struct clk *div, struct clk *mux, struct clk *pll,
+		struct clk *step);
+
 #endif