[PATCH 1/3] powerpc/85xx: Add clock driver for PWM
Chunhe Lan
Chunhe.Lan at freescale.com
Tue Jan 10 21:26:41 EST 2012
Plugs into the generic powerpc clock driver in
arch/powerpc/kernel/clock.c
The following subset of clk_interface is implemented:
clk_get: get clock via name
clk_put: stubbed
clk_enable: enable clock
clk_disable: disable clock
clk_get_rate: get clock rate in Hz
clk_set_rate: NULL
clk_round_rate: NULL
clk_set_parent: NULL
clk_get_parent: NULL
Signed-off-by: Chunhe Lan <Chunhe.Lan at freescale.com>
---
arch/powerpc/include/asm/clock.h | 33 +++++++
arch/powerpc/platforms/85xx/Makefile | 1 +
arch/powerpc/platforms/85xx/pwm-clock.c | 161 +++++++++++++++++++++++++++++++
3 files changed, 195 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/include/asm/clock.h
create mode 100644 arch/powerpc/platforms/85xx/pwm-clock.c
diff --git a/arch/powerpc/include/asm/clock.h b/arch/powerpc/include/asm/clock.h
new file mode 100644
index 0000000..98447eb
--- /dev/null
+++ b/arch/powerpc/include/asm/clock.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Chunhe Lan <Chunhe.Lan at freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+struct clk {
+ struct list_head node;
+ const char *name; /* unique clock name */
+ const char *function; /* function of the clock */
+ struct device *dev; /* device associated with function */
+ unsigned int id:2; /* clock identification */
+ unsigned long rate_hz;
+ struct clk *parent;
+ void (*mode)(struct clk *clk, int status);
+ u16 users;
+};
+
+extern int clk_register(struct clk *clk);
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile
index bc5acb9..ba0d0a9 100644
--- a/arch/powerpc/platforms/85xx/Makefile
+++ b/arch/powerpc/platforms/85xx/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_P3041_DS) += p3041_ds.o corenet_ds.o
obj-$(CONFIG_P3060_QDS) += p3060_qds.o corenet_ds.o
obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o
obj-$(CONFIG_P5020_DS) += p5020_ds.o corenet_ds.o
+obj-$(CONFIG_FSL_PWM) += pwm-clock.o
obj-$(CONFIG_STX_GP3) += stx_gp3.o
obj-$(CONFIG_TQM85xx) += tqm85xx.o
obj-$(CONFIG_SBC8560) += sbc8560.o
diff --git a/arch/powerpc/platforms/85xx/pwm-clock.c b/arch/powerpc/platforms/85xx/pwm-clock.c
new file mode 100644
index 0000000..bba9872
--- /dev/null
+++ b/arch/powerpc/platforms/85xx/pwm-clock.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * Implements the clk api defined in include/linux/clk.h
+ *
+ * Author: Chunhe Lan <Chunhe.Lan at freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/of_platform.h>
+#include <asm/clk_interface.h>
+#include <asm/clock.h>
+
+static LIST_HEAD(clocks);
+static DEFINE_SPINLOCK(clk_lock);
+
+static struct clk pwm_clk = {
+ .name = "pwm-clk",
+ .rate_hz = 0,
+ .users = 1, /* always on */
+ .id = 0,
+};
+
+static struct clk *all_clocks[] __initdata = {
+ &pwm_clk,
+};
+
+/* clocks cannot be de-registered no refcounting necessary */
+static struct clk *fsl_clk_get(struct device *dev, const char *id)
+{
+ struct clk *clk;
+
+ list_for_each_entry(clk, &clocks, node) {
+ if (strcmp(id, clk->name) == 0)
+ return clk;
+ }
+
+ return ERR_PTR(-ENOENT);
+}
+
+static void fsl_clk_put(struct clk *clk)
+{
+}
+
+static void __clk_enable(struct clk *clk)
+{
+ if (clk->parent)
+ __clk_enable(clk->parent);
+ if (clk->users++ == 0 && clk->mode)
+ clk->mode(clk, 1);
+}
+
+static int fsl_clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ __clk_enable(clk);
+ spin_unlock_irqrestore(&clk_lock, flags);
+
+ return 0;
+}
+
+static void __clk_disable(struct clk *clk)
+{
+ BUG_ON(clk->users == 0);
+
+ if (--clk->users == 0 && clk->mode)
+ clk->mode(clk, 0);
+ if (clk->parent)
+ __clk_disable(clk->parent);
+}
+
+static void fsl_clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ __clk_disable(clk);
+ spin_unlock_irqrestore(&clk_lock, flags);
+}
+
+static unsigned long fsl_clk_get_rate(struct clk *clk)
+{
+ unsigned long flags;
+ unsigned long rate;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ for (;;) {
+ rate = clk->rate_hz;
+ if (rate || !clk->parent)
+ break;
+ clk = clk->parent;
+ }
+ spin_unlock_irqrestore(&clk_lock, flags);
+
+ return rate;
+}
+
+static struct clk_interface fsl_clk_functions = {
+ .clk_get = fsl_clk_get,
+ .clk_put = fsl_clk_put,
+ .clk_enable = fsl_clk_enable,
+ .clk_disable = fsl_clk_disable,
+ .clk_get_rate = fsl_clk_get_rate,
+};
+
+/* Register a new clock */
+int clk_register(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clk_lock, flags);
+ list_add(&clk->node, &clocks);
+ spin_unlock_irqrestore(&clk_lock, flags);
+
+ return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+static int fsl_register_clocks(void)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(all_clocks); i++)
+ clk_register(all_clocks[i]);
+
+ return 0;
+}
+
+static int __init fsl_clk_init(void)
+{
+ fsl_register_clocks();
+ clk_functions = fsl_clk_functions;
+
+ return 0;
+}
+
+arch_initcall(fsl_clk_init);
--
1.5.6.5
More information about the Linuxppc-dev
mailing list