2008-02-02 22:54:48

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH 0/5] Generic clocks framework

Hi,

Currently we have a generic clock api for using clocks.
This patchset tries to fill other side: an api for providing
clocks.
Currently each platform that wants to provide <linux/clk.h>
implementation is forced to reimplement everything from scratch.
This leads for major code duplication. E.g. the ARM arch
contains 13 implementations (one for each mach). Also there are
implementations for AVR, MIPS, PowerPC and SH.

This patchset implements the "management" part, so each platform
would have to only implement few platform-specific parts.

--
With best wishes
Dmitry


2008-02-02 23:00:42

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH 2/5] Clocklib debugfs support

Provide /sys/kernel/debug/clock to ease debugging.

Signed-off-by: Dmitry Baryshkov <[email protected]>
---
include/linux/clklib.h | 5 +++
kernel/clklib.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 73 insertions(+), 0 deletions(-)

diff --git a/include/linux/clklib.h b/include/linux/clklib.h
index 4bd9b4a..f916693 100644
--- a/include/linux/clklib.h
+++ b/include/linux/clklib.h
@@ -28,6 +28,11 @@ struct clk {
int (*setrate) (struct clk *, unsigned long);
long (*roundrate) (struct clk *, unsigned long);

+ /*
+ * format any additional info
+ */
+ int (*format) (struct clk *, struct seq_file *);
+
void *priv;
};

diff --git a/kernel/clklib.c b/kernel/clklib.c
index 203af3d..b782220 100644
--- a/kernel/clklib.c
+++ b/kernel/clklib.c
@@ -293,3 +293,71 @@ out:
return rc;
}
EXPORT_SYMBOL(clk_alloc_function);
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+static void dump_clocks(struct seq_file *s, struct clk *parent, int nest)
+{
+ struct clk *clk;
+ int i;
+
+ list_for_each_entry(clk, &clocks, node) {
+ if (clk->parent == parent) {
+ for (i = 0; i < nest; i++)
+ seq_putc(s, ' ');
+ seq_puts(s, clk->name);
+
+ i = nest + strlen(clk->name);
+ if (i >= 16)
+ i = 15;
+ for (; i < 16; i++)
+ seq_putc(s, ' ');
+ seq_printf(s, "%c use=%d rate=%lu KHz",
+ clk->set_parent ? '*' : ' ',
+ clk->users,
+ __clk_get_rate(clk));
+ if (clk->format)
+ clk->format(clk, s);
+ seq_putc(s, '\n');
+
+ dump_clocks(s, clk, nest + 1);
+ }
+ }
+}
+
+static int clocklib_show(struct seq_file *s, void *unused)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+
+ dump_clocks(s, NULL, 0);
+
+ spin_unlock_irqrestore(&clocks_lock, flags);
+
+ return 0;
+}
+
+static int clocklib_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, clocklib_show, NULL);
+}
+
+static struct file_operations clocklib_operations = {
+ .open = clocklib_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init clocklib_debugfs_init(void)
+{
+ debugfs_create_file("clock", S_IFREG | S_IRUGO,
+ NULL, NULL, &clocklib_operations);
+ return 0;
+}
+subsys_initcall(clocklib_debugfs_init);
+
+#endif /* DEBUG_FS */
--
1.5.3.8


--
With best wishes
Dmitry

2008-02-02 23:01:04

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH 1/5] Add generic framework for managing clocks.

Provide a generic framework that platform may choose
to support clocks api. In particular this provides
platform-independant struct clk definition, a full
implementation of clocks api and a set of functions
for registering and unregistering clocks in a safe way.

Signed-off-by: Dmitry Baryshkov <[email protected]>
---
include/linux/clklib.h | 85 ++++++++++++++
init/Kconfig | 7 +
kernel/Makefile | 1 +
kernel/clklib.c | 295 ++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 388 insertions(+), 0 deletions(-)

diff --git a/include/linux/clklib.h b/include/linux/clklib.h
new file mode 100644
index 0000000..4bd9b4a
--- /dev/null
+++ b/include/linux/clklib.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2008 Dmitry Baryshkov
+ *
+ * This file is released under the GPL v2.
+ */
+
+#ifndef CLKLIB_H
+#define CLKLIB_H
+
+#include <linux/list.h>
+
+struct clk {
+ struct list_head node;
+ struct clk *parent;
+
+ const char *name;
+ struct module *owner;
+
+ int users;
+ unsigned long rate;
+ int delay;
+
+ int (*can_get) (struct clk *, struct device *);
+ int (*set_parent) (struct clk *, struct clk *);
+ int (*enable) (struct clk *);
+ void (*disable) (struct clk *);
+ unsigned long (*getrate) (struct clk*);
+ int (*setrate) (struct clk *, unsigned long);
+ long (*roundrate) (struct clk *, unsigned long);
+
+ void *priv;
+};
+
+int clk_register(struct clk *clk);
+void clk_unregister(struct clk *clk);
+static void __maybe_unused clks_register(struct clk *clks, size_t num)
+{
+ int i;
+ for (i = 0; i < num; i++) {
+ clk_register(&clks[i]);
+ }
+}
+
+
+int clk_alloc_function(const char *parent, struct clk *clk);
+
+struct clk_function {
+ const char *parent;
+ struct clk *clk;
+};
+
+#define CLK_FUNC(_clock, _function, _can_get, _data, _format) \
+ { \
+ .parent = _clock, \
+ .clk = &(struct clk) { \
+ .name= _function, \
+ .owner = THIS_MODULE, \
+ .can_get = _can_get, \
+ .priv = _data, \
+ .format = _format, \
+ }, \
+ }
+
+static int __maybe_unused clk_alloc_functions(
+ struct clk_function *funcs,
+ int num)
+{
+ int i;
+ int rc;
+
+ for (i = 0; i < num; i++) {
+ rc = clk_alloc_function(funcs[i].parent, funcs[i].clk);
+
+ if (rc) {
+ printk(KERN_ERR "Error allocating %s.%s function.\n",
+ funcs[i].parent,
+ funcs[i].clk->name);
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
+#endif
diff --git a/init/Kconfig b/init/Kconfig
index dcc96a8..18d53c1 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -444,6 +444,13 @@ config CC_OPTIMIZE_FOR_SIZE
config SYSCTL
bool

+config HAVE_CLOCK_LIB
+ bool
+ help
+ Platforms select clocklib if they use this infrastructure
+ for managing their clocks both built into SoC and provided
+ by external devices.
+
menuconfig EMBEDDED
bool "Configure standard kernel features (for small systems)"
help
diff --git a/kernel/Makefile b/kernel/Makefile
index 8885627..0bc929a 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -65,6 +65,7 @@ obj-$(CONFIG_TASK_DELAY_ACCT) += delayacct.o
obj-$(CONFIG_TASKSTATS) += taskstats.o tsacct.o
obj-$(CONFIG_MARKERS) += marker.o
obj-$(CONFIG_LATENCYTOP) += latencytop.o
+obj-$(CONFIG_HAVE_CLOCK_LIB) += clklib.o

ifneq ($(CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER),y)
# According to Alan Modra <[email protected]>, the -fno-omit-frame-pointer is
diff --git a/kernel/clklib.c b/kernel/clklib.c
new file mode 100644
index 0000000..203af3d
--- /dev/null
+++ b/kernel/clklib.c
@@ -0,0 +1,295 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/clklib.h>
+#include <linux/spinlock.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+static LIST_HEAD(clocks);
+static DEFINE_SPINLOCK(clocks_lock);
+
+static int __clk_register(struct clk *clk)
+{
+ if (clk->parent &&
+ !try_module_get(clk->parent->owner))
+ return -EINVAL;
+
+ list_add_tail(&clk->node, &clocks);
+
+ return 0;
+}
+
+int clk_register(struct clk *clk)
+{
+ unsigned long flags;
+ int rc;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+
+ rc = __clk_register(clk);
+
+ spin_unlock_irqrestore(&clocks_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+ list_del(&clk->node);
+ if (clk->parent)
+ module_put(clk->parent->owner);
+ spin_unlock_irqrestore(&clocks_lock, flags);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ struct clk *p, *clk = ERR_PTR(-ENOENT);
+ unsigned long flags;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+
+ list_for_each_entry(p, &clocks, node) {
+ if (strcmp(id, p->name) == 0 &&
+ (!p->can_get || p->can_get(p, dev)) &&
+ try_module_get(p->owner)) {
+ clk = p;
+ break;
+ }
+ }
+
+ spin_unlock_irqrestore(&clocks_lock, flags);
+
+ return clk;
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (!clk || IS_ERR(clk))
+ return;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+
+ module_put(clk->owner);
+
+ spin_unlock_irqrestore(&clocks_lock, flags);
+}
+EXPORT_SYMBOL(clk_put);
+
+int clk_set_parent(struct clk *clk, struct clk *parent)
+{
+ int rc;
+ unsigned long flags;
+
+ if (!clk || IS_ERR(clk))
+ return -EINVAL;
+
+ if (!clk->set_parent)
+ return -EINVAL;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+
+ rc = clk->set_parent(clk, parent);
+ if (!rc)
+ clk->parent = parent;
+
+ spin_unlock_irqrestore(&clocks_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL(clk_set_parent);
+
+static int __clk_enable(struct clk *clk)
+{
+ int rc = 0;
+
+ if (clk->parent) {
+ rc = __clk_enable(clk->parent);
+
+ if (rc)
+ return rc;
+ }
+
+ if (clk->users++ == 0)
+ if (clk->enable)
+ rc = clk->enable(clk);
+
+ if (clk->delay)
+ udelay(clk->delay);
+
+ return rc;
+}
+
+int clk_enable(struct clk *clk)
+{
+ unsigned long flags;
+ int rc;
+
+ if (!clk || IS_ERR(clk))
+ return -EINVAL;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+
+ rc = __clk_enable(clk);
+
+ spin_unlock_irqrestore(&clocks_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL(clk_enable);
+
+static void __clk_disable(struct clk *clk)
+{
+ if (clk->users <= 0) {
+ WARN_ON(1);
+ return;
+ }
+
+ if (--clk->users == 0)
+ if (clk->disable)
+ clk->disable(clk);
+
+ if (clk->parent)
+ __clk_disable(clk->parent);
+}
+
+void clk_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ if (!clk || IS_ERR(clk))
+ return;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+
+ __clk_disable(clk);
+
+ spin_unlock_irqrestore(&clocks_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+static unsigned long __clk_get_rate(struct clk *clk)
+{
+ unsigned long rate = 0;
+
+ for (;;) {
+ if (rate || !clk)
+ return rate;
+
+ if (clk->getrate)
+ rate = clk->getrate(clk);
+ else if (clk->rate)
+ rate = clk->rate;
+ else
+ clk = clk->parent;
+ }
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ unsigned long rate = 0;
+ unsigned long flags;
+
+ if (!clk || IS_ERR(clk))
+ return -EINVAL;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+
+ rate = __clk_get_rate(clk);
+
+ spin_unlock_irqrestore(&clocks_lock, flags);
+
+ return rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+long clk_round_rate(struct clk *clk, unsigned long rate)
+{
+ long res;
+ unsigned long flags;
+
+ if (!clk || IS_ERR(clk))
+ return -EINVAL;
+
+ if (!clk->roundrate)
+ return -EINVAL;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+
+ res = clk->roundrate(clk, rate);
+
+ spin_unlock_irqrestore(&clocks_lock, flags);
+
+ return res;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+ int rc;
+ unsigned long flags;
+
+ if (!clk || IS_ERR(clk))
+ return -EINVAL;
+
+ if (!clk->setrate)
+ return -EINVAL;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+
+ rc = clk->setrate(clk, rate);
+
+ spin_unlock_irqrestore(&clocks_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_alloc_function(const char *parent, struct clk *clk)
+{
+ int rc = 0;
+ unsigned long flags;
+ struct clk *pclk;
+ bool found = false;
+
+ spin_lock_irqsave(&clocks_lock, flags);
+
+ list_for_each_entry(pclk, &clocks, node) {
+ if (strcmp(parent, pclk->name) == 0 &&
+ try_module_get(pclk->owner)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ rc = -ENODEV;
+ goto out;
+ }
+
+ clk->parent = pclk;
+
+ __clk_register(clk);
+ /*
+ * We locked parent owner during search
+ * and also in __clk_register. Free one reference
+ */
+ module_put(pclk->owner);
+
+out:
+ if (rc) {
+ kfree(clk);
+ }
+ spin_unlock_irqrestore(&clocks_lock, flags);
+
+ return rc;
+}
+EXPORT_SYMBOL(clk_alloc_function);
--
1.5.3.8


--
With best wishes
Dmitry

2008-02-02 23:01:35

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH 3/5] Use clocklib for ARM pxa sub-arch.

Signed-off-by: Dmitry Baryshkov <[email protected]>
---
arch/arm/Kconfig | 1 +
arch/arm/mach-pxa/clock.c | 108 ++++----------------------
arch/arm/mach-pxa/clock.h | 58 +++++++-------
arch/arm/mach-pxa/pxa25x.c | 187 +++++++++++++++++++++++++++++++++++++------
arch/arm/mach-pxa/pxa27x.c | 61 ++++++++-------
arch/arm/mach-pxa/pxa3xx.c | 91 ++++++++++++---------
6 files changed, 292 insertions(+), 214 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 4b1a8e3..45c1790 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -362,6 +362,7 @@ config ARCH_PXA
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
select TICK_ONESHOT
+ select HAVE_CLOCK_LIB
help
Support for Intel/Marvell's PXA2xx/PXA3xx processor line.

diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c
index 83ef5ec..3296b02 100644
--- a/arch/arm/mach-pxa/clock.c
+++ b/arch/arm/mach-pxa/clock.c
@@ -8,6 +8,7 @@
#include <linux/err.h>
#include <linux/string.h>
#include <linux/clk.h>
+#include <linux/clklib.h>
#include <linux/spinlock.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
@@ -19,123 +20,42 @@
#include "generic.h"
#include "clock.h"

-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-static DEFINE_SPINLOCK(clocks_lock);
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
- struct clk *p, *clk = ERR_PTR(-ENOENT);
-
- mutex_lock(&clocks_mutex);
- list_for_each_entry(p, &clocks, node) {
- if (strcmp(id, p->name) == 0 &&
- (p->dev == NULL || p->dev == dev)) {
- clk = p;
- break;
- }
- }
- mutex_unlock(&clocks_mutex);
-
- return clk;
-}
-EXPORT_SYMBOL(clk_get);
-
-void clk_put(struct clk *clk)
+static int clk_gpio27_enable(struct clk *clk)
{
-}
-EXPORT_SYMBOL(clk_put);
-
-int clk_enable(struct clk *clk)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&clocks_lock, flags);
- if (clk->enabled++ == 0)
- clk->ops->enable(clk);
- spin_unlock_irqrestore(&clocks_lock, flags);
-
- if (clk->delay)
- udelay(clk->delay);
+ pxa_gpio_mode(GPIO11_3_6MHz_MD);

return 0;
}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
- unsigned long flags;
-
- WARN_ON(clk->enabled == 0);
-
- spin_lock_irqsave(&clocks_lock, flags);
- if (--clk->enabled == 0)
- clk->ops->disable(clk);
- spin_unlock_irqrestore(&clocks_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
- unsigned long rate;
-
- rate = clk->rate;
- if (clk->ops->getrate)
- rate = clk->ops->getrate(clk);
-
- return rate;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-
-static void clk_gpio27_enable(struct clk *clk)
-{
- pxa_gpio_mode(GPIO11_3_6MHz_MD);
-}

static void clk_gpio27_disable(struct clk *clk)
{
+ /* FIXME: disable clock */
}

-static const struct clkops clk_gpio27_ops = {
- .enable = clk_gpio27_enable,
- .disable = clk_gpio27_disable,
-};
-
-
-void clk_cken_enable(struct clk *clk)
+int clk_cken_enable(struct clk *clk)
{
- CKEN |= 1 << clk->cken;
+ int cken = ((struct clk_cken_priv *)clk->priv)->cken;
+ CKEN |= 1 << cken;
+
+ return 0;
}

void clk_cken_disable(struct clk *clk)
{
- CKEN &= ~(1 << clk->cken);
+ int cken = ((struct clk_cken_priv *)clk->priv)->cken;
+ CKEN &= ~(1 << cken);
}

-const struct clkops clk_cken_ops = {
- .enable = clk_cken_enable,
- .disable = clk_cken_disable,
-};
-
static struct clk common_clks[] = {
{
.name = "GPIO27_CLK",
- .ops = &clk_gpio27_ops,
.rate = 3686400,
+ .owner = THIS_MODULE,
+ .enable = clk_gpio27_enable,
+ .disable = clk_gpio27_disable,
},
};

-void clks_register(struct clk *clks, size_t num)
-{
- int i;
-
- mutex_lock(&clocks_mutex);
- for (i = 0; i < num; i++)
- list_add(&clks[i].node, &clocks);
- mutex_unlock(&clocks_mutex);
-}
-
static int __init clk_init(void)
{
clks_register(common_clks, ARRAY_SIZE(common_clks));
diff --git a/arch/arm/mach-pxa/clock.h b/arch/arm/mach-pxa/clock.h
index bc6b77e..5d0d067 100644
--- a/arch/arm/mach-pxa/clock.h
+++ b/arch/arm/mach-pxa/clock.h
@@ -1,43 +1,47 @@
-struct clk;
+#include <linux/clklib.h>
+#include <linux/seq_file.h>

-struct clkops {
- void (*enable)(struct clk *);
- void (*disable)(struct clk *);
- unsigned long (*getrate)(struct clk *);
+struct clk_cken_priv {
+ unsigned int cken;
};

-struct clk {
- struct list_head node;
- const char *name;
- struct device *dev;
- const struct clkops *ops;
- unsigned long rate;
- unsigned int cken;
- unsigned int delay;
- unsigned int enabled;
-};
-
-#define INIT_CKEN(_name, _cken, _rate, _delay, _dev) \
+#define INIT_CKEN(_name, _cken, _rate, _delay) \
{ \
.name = _name, \
- .dev = _dev, \
- .ops = &clk_cken_ops, \
+ .enable = clk_cken_enable, \
+ .disable = clk_cken_disable, \
.rate = _rate, \
- .cken = CKEN_##_cken, \
.delay = _delay, \
+ .priv = &(struct clk_cken_priv) { \
+ .cken = CKEN_##_cken, \
+ }, \
}

-#define INIT_CK(_name, _cken, _ops, _dev) \
+#define INIT_CK(_name, _cken, _getrate) \
{ \
.name = _name, \
- .dev = _dev, \
- .ops = _ops, \
- .cken = CKEN_##_cken, \
+ .enable = clk_cken_enable, \
+ .disable = clk_cken_disable, \
+ .getrate = _getrate, \
+ .priv = &(struct clk_cken_priv) { \
+ .cken = CKEN_##_cken, \
+ }, \
}

-extern const struct clkops clk_cken_ops;
-
-void clk_cken_enable(struct clk *clk);
+int clk_cken_enable(struct clk *clk);
void clk_cken_disable(struct clk *clk);

void clks_register(struct clk *clks, size_t num);
+
+static int __maybe_unused clk_dev_can_get(struct clk *clk, struct device *dev)
+{
+ return (dev == clk->priv);
+}
+
+static int __maybe_unused clk_dev_format(struct clk *clk, struct seq_file *s)
+{
+ BUG_ON(!clk->priv);
+ seq_puts(s, "for device ");
+ seq_puts(s, ((struct device *)clk->priv)->bus_id);
+ return 0;
+}
diff --git a/arch/arm/mach-pxa/pxa25x.c b/arch/arm/mach-pxa/pxa25x.c
index ddd05bf..e9e639d 100644
--- a/arch/arm/mach-pxa/pxa25x.c
+++ b/arch/arm/mach-pxa/pxa25x.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/suspend.h>
+#include <linux/dma-mapping.h>

#include <asm/hardware.h>
#include <asm/arch/irqs.h>
@@ -32,6 +33,128 @@
#include "devices.h"
#include "clock.h"

+
+static u64 pxa25x_ssp_dma_mask = DMA_BIT_MASK(32);
+
+static struct resource pxa25x_resource_ssp[] = {
+#if 0
+ [0] = {
+ .start = 0x41000000,
+ .end = 0x4100001f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_SSP,
+ .end = IRQ_SSP,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* DRCMR for RX */
+ .start = 13,
+ .end = 13,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ /* DRCMR for TX */
+ .start = 14,
+ .end = 14,
+ .flags = IORESOURCE_DMA,
+ },
+#endif
+};
+
+struct platform_device pxa25x_device_ssp = {
+ .name = "pxa25x-ssp",
+ .id = 0,
+ .dev = {
+ .dma_mask = &pxa25x_ssp_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .resource = pxa25x_resource_ssp,
+ .num_resources = ARRAY_SIZE(pxa25x_resource_ssp),
+};
+
+static u64 pxa25x_nssp_dma_mask = DMA_BIT_MASK(32);
+
+static struct resource pxa25x_resource_nssp[] = {
+#if 0
+ [0] = {
+ .start = 0x41400000,
+ .end = 0x4140002f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_NSSP,
+ .end = IRQ_NSSP,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* DRCMR for RX */
+ .start = 15,
+ .end = 15,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ /* DRCMR for TX */
+ .start = 16,
+ .end = 16,
+ .flags = IORESOURCE_DMA,
+ },
+#endif
+};
+
+struct platform_device pxa25x_device_nssp = {
+ .name = "pxa25x-nssp",
+ .id = 1,
+ .dev = {
+ .dma_mask = &pxa25x_nssp_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .resource = pxa25x_resource_nssp,
+ .num_resources = ARRAY_SIZE(pxa25x_resource_nssp),
+};
+
+static u64 pxa25x_assp_dma_mask = DMA_BIT_MASK(32);
+
+static struct resource pxa25x_resource_assp[] = {
+#if 0
+ [0] = {
+ .start = 0x41500000,
+ .end = 0x4150002f,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .start = IRQ_ASSP,
+ .end = IRQ_ASSP,
+ .flags = IORESOURCE_IRQ,
+ },
+ [2] = {
+ /* DRCMR for RX */
+ .start = 23,
+ .end = 23,
+ .flags = IORESOURCE_DMA,
+ },
+ [3] = {
+ /* DRCMR for TX */
+ .start = 24,
+ .end = 24,
+ .flags = IORESOURCE_DMA,
+ },
+#endif
+};
+
+struct platform_device pxa25x_device_assp = {
+ /* ASSP is basically equivalent to NSSP */
+ .name = "pxa25x-nssp",
+ .id = 2,
+ .dev = {
+ .dma_mask = &pxa25x_assp_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .resource = pxa25x_resource_assp,
+ .num_resources = ARRAY_SIZE(pxa25x_resource_assp),
+};
+
/*
* Various clock factors driven by the CCCR register.
*/
@@ -100,40 +223,50 @@ static unsigned long clk_pxa25x_lcd_getrate(struct clk *clk)
return pxa25x_get_memclk_frequency_10khz() * 10000;
}

-static const struct clkops clk_pxa25x_lcd_ops = {
- .enable = clk_cken_enable,
- .disable = clk_cken_disable,
- .getrate = clk_pxa25x_lcd_getrate,
-};
-
/*
* 3.6864MHz -> OST, GPIO, SSP, PWM, PLLs (95.842MHz, 147.456MHz)
* 95.842MHz -> MMC 19.169MHz, I2C 31.949MHz, FICP 47.923MHz, USB 47.923MHz
* 147.456MHz -> UART 14.7456MHz, AC97 12.288MHz, I2S 5.672MHz (allegedly)
*/
-static struct clk pxa25x_hwuart_clk =
- INIT_CKEN("UARTCLK", HWUART, 14745600, 1, &pxa_device_hwuart.dev)
-;
+static struct clk pxa25x_hwuart_clk[] = {
+ INIT_CKEN("HWUARTCLK", HWUART, 14745600, 1),
+ {
+ .parent = &pxa25x_hwuart_clk[0],
+ .name = "UARTCLK",
+ .can_get = clk_dev_can_get,
+ .priv = &pxa_device_hwuart.dev,
+ },
+};

static struct clk pxa25x_clks[] = {
- INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_ops, &pxa_device_fb.dev),
- INIT_CKEN("UARTCLK", FFUART, 14745600, 1, &pxa_device_ffuart.dev),
- INIT_CKEN("UARTCLK", BTUART, 14745600, 1, &pxa_device_btuart.dev),
- INIT_CKEN("UARTCLK", STUART, 14745600, 1, NULL),
- INIT_CKEN("UDCCLK", USB, 47923000, 5, &pxa_device_udc.dev),
- INIT_CKEN("MMCCLK", MMC, 19169000, 0, &pxa_device_mci.dev),
- INIT_CKEN("I2CCLK", I2C, 31949000, 0, &pxa_device_i2c.dev),
-
- INIT_CKEN("SSPCLK", SSP, 3686400, 0, &pxa25x_device_ssp.dev),
- INIT_CKEN("SSPCLK", NSSP, 3686400, 0, &pxa25x_device_nssp.dev),
- INIT_CKEN("SSPCLK", ASSP, 3686400, 0, &pxa25x_device_assp.dev),
+ INIT_CK("LCDCLK", LCD, &clk_pxa25x_lcd_getrate),
+ INIT_CKEN("FFUARTCLK", FFUART, 14745600, 1),
+ INIT_CKEN("BTUARTCLK", BTUART, 14745600, 1),
+ INIT_CKEN("STUARTCLK", STUART, 14745600, 1),
+ INIT_CKEN("UDCCLK", USB, 47923000, 5),
+ INIT_CKEN("MMCCLK", MMC, 19169000, 0),
+ INIT_CKEN("I2CCLK", I2C, 31949000, 0),
+
+ INIT_CKEN("SSP_CLK", SSP, 3686400, 0),
+ INIT_CKEN("NSSPCLK", NSSP, 3686400, 0),
+ INIT_CKEN("ASSPCLK", ASSP, 3686400, 0),

/*
- INIT_CKEN("PWMCLK", PWM0, 3686400, 0, NULL),
- INIT_CKEN("PWMCLK", PWM0, 3686400, 0, NULL),
- INIT_CKEN("I2SCLK", I2S, 14745600, 0, NULL),
+ INIT_CKEN("PWMCLK", PWM0, 3686400, 0),
+ INIT_CKEN("PWMCLK", PWM0, 3686400, 0),
+ INIT_CKEN("I2SCLK", I2S, 14745600, 0),
*/
- INIT_CKEN("FICPCLK", FICP, 47923000, 0, NULL),
+ INIT_CKEN("FICPCLK", FICP, 47923000, 0),
+};
+
+static struct clk_function __initdata pxa25x_clk_funcs[] = {
+ CLK_FUNC("FFUARTCLK", "UARTCLK", clk_dev_can_get, &pxa_device_ffuart.dev, clk_dev_format),
+ CLK_FUNC("BTUARTCLK", "UARTCLK", clk_dev_can_get, &pxa_device_btuart.dev, clk_dev_format),
+ CLK_FUNC("STUARTCLK", "UARTCLK", clk_dev_can_get, &pxa_device_stuart.dev, clk_dev_format),
+ CLK_FUNC("STUARTCLK", "SIRCLK", NULL, NULL, NULL),
+ CLK_FUNC("SSP_CLK", "SSPCLK", clk_dev_can_get, &pxa25x_device_ssp.dev, clk_dev_format),
+ CLK_FUNC("NSSPCLK", "SSPCLK", clk_dev_can_get, &pxa25x_device_nssp.dev, clk_dev_format),
+ CLK_FUNC("ASSPCLK", "SSPCLK", clk_dev_can_get, &pxa25x_device_assp.dev, clk_dev_format),
};

#ifdef CONFIG_PM
@@ -309,11 +442,13 @@ static int __init pxa25x_init(void)
int ret = 0;

/* Only add HWUART for PXA255/26x; PXA210/250/27x do not have it. */
- if (cpu_is_pxa25x())
- clks_register(&pxa25x_hwuart_clk, 1);
+ if (cpu_is_pxa25x()) {
+ clks_register(pxa25x_hwuart_clk, ARRAY_SIZE(pxa25x_hwuart_clk));
+ }

if (cpu_is_pxa21x() || cpu_is_pxa25x()) {
clks_register(pxa25x_clks, ARRAY_SIZE(pxa25x_clks));
+ clk_alloc_functions(pxa25x_clk_funcs, ARRAY_SIZE(pxa25x_clk_funcs));

if ((ret = pxa_init_dma(16)))
return ret;
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 96cf274..188934a 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -128,44 +128,48 @@ static unsigned long clk_pxa27x_lcd_getrate(struct clk *clk)
return pxa27x_get_lcdclk_frequency_10khz() * 10000;
}

-static const struct clkops clk_pxa27x_lcd_ops = {
- .enable = clk_cken_enable,
- .disable = clk_cken_disable,
- .getrate = clk_pxa27x_lcd_getrate,
-};
-
static struct clk pxa27x_clks[] = {
- INIT_CK("LCDCLK", LCD, &clk_pxa27x_lcd_ops, &pxa_device_fb.dev),
- INIT_CK("CAMCLK", CAMERA, &clk_pxa27x_lcd_ops, NULL),
+ INIT_CK("LCDCLK", LCD, &clk_pxa27x_lcd_getrate),
+ INIT_CK("CAMCLK", CAMERA, &clk_pxa27x_lcd_getrate),

- INIT_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
- INIT_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
- INIT_CKEN("UARTCLK", STUART, 14857000, 1, NULL),
+ INIT_CKEN("FFUARTCLK", FFUART, 14857000, 1),
+ INIT_CKEN("BTUARTCLK", BTUART, 14857000, 1),
+ INIT_CKEN("STUARTCLK", STUART, 14857000, 1),

- INIT_CKEN("I2SCLK", I2S, 14682000, 0, &pxa_device_i2s.dev),
- INIT_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev),
- INIT_CKEN("UDCCLK", USB, 48000000, 5, &pxa_device_udc.dev),
- INIT_CKEN("MMCCLK", MMC, 19500000, 0, &pxa_device_mci.dev),
- INIT_CKEN("FICPCLK", FICP, 48000000, 0, &pxa_device_ficp.dev),
+ INIT_CKEN("I2SCLK", I2S, 14682000, 0),
+ INIT_CKEN("I2CCLK", I2C, 32842000, 0),
+ INIT_CKEN("UDCCLK", USB, 48000000, 5),
+ INIT_CKEN("MMCCLK", MMC, 19500000, 0),
+ INIT_CKEN("FICPCLK", FICP, 48000000, 0),

- INIT_CKEN("USBCLK", USBHOST, 48000000, 0, &pxa27x_device_ohci.dev),
- INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0, &pxa27x_device_i2c_power.dev),
- INIT_CKEN("KBDCLK", KEYPAD, 32768, 0, NULL),
+ INIT_CKEN("USBCLK", USBHOST, 48000000, 0),
+ INIT_CKEN("I2CCLK", PWRI2C, 13000000, 0),
+ INIT_CKEN("KBDCLK", KEYPAD, 32768, 0),

- INIT_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev),
- INIT_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev),
- INIT_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev),
+ INIT_CKEN("SSP1CLK", SSP1, 13000000, 0),
+ INIT_CKEN("SSP2CLK", SSP2, 13000000, 0),
+ INIT_CKEN("SSP3CLK", SSP3, 13000000, 0),

/*
- INIT_CKEN("PWMCLK", PWM0, 13000000, 0, NULL),
- INIT_CKEN("MSLCLK", MSL, 48000000, 0, NULL),
- INIT_CKEN("USIMCLK", USIM, 48000000, 0, NULL),
- INIT_CKEN("MSTKCLK", MEMSTK, 19500000, 0, NULL),
- INIT_CKEN("IMCLK", IM, 0, 0, NULL),
- INIT_CKEN("MEMCLK", MEMC, 0, 0, NULL),
+ INIT_CKEN("PWMCLK", PWM0, 13000000, 0),
+ INIT_CKEN("MSLCLK", MSL, 48000000, 0),
+ INIT_CKEN("USIMCLK", USIM, 48000000, 0),
+ INIT_CKEN("MSTKCLK", MEMSTK, 19500000, 0),
+ INIT_CKEN("IMCLK", IM, 0, 0),
+ INIT_CKEN("MEMCLK", MEMC, 0, 0),
*/
};

+static struct clk_function __initdata pxa27x_clk_funcs[] = {
+ CLK_FUNC("FFUARTCLK", "UARTCLK", clk_dev_can_get, &pxa_device_ffuart.dev, clk_dev_format),
+ CLK_FUNC("BTUARTCLK", "UARTCLK", clk_dev_can_get, &pxa_device_btuart.dev, clk_dev_format),
+ CLK_FUNC("STUARTCLK", "UARTCLK", clk_dev_can_get, &pxa_device_stuart.dev, clk_dev_format),
+ CLK_FUNC("STUARTCLK", "SIRCLK", NULL, NULL, NULL),
+ CLK_FUNC("SSP1CLK", "SSPCLK", clk_dev_can_get, &pxa27x_device_ssp1.dev, clk_dev_format),
+ CLK_FUNC("SSP2CLK", "SSPCLK", clk_dev_can_get, &pxa27x_device_ssp2.dev, clk_dev_format),
+ CLK_FUNC("SSP3CLK", "SSPCLK", clk_dev_can_get, &pxa27x_device_ssp3.dev, clk_dev_format),
+};
+
#ifdef CONFIG_PM

#define SAVE(x) sleep_save[SLEEP_SAVE_##x] = x
@@ -414,6 +418,7 @@ static int __init pxa27x_init(void)
int ret = 0;
if (cpu_is_pxa27x()) {
clks_register(pxa27x_clks, ARRAY_SIZE(pxa27x_clks));
+ clk_alloc_functions(pxa27x_clk_funcs, ARRAY_SIZE(pxa27x_clk_funcs));

if ((ret = pxa_init_dma(32)))
return ret;
diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c
index 5cbf057..6b6440c 100644
--- a/arch/arm/mach-pxa/pxa3xx.c
+++ b/arch/arm/mach-pxa/pxa3xx.c
@@ -123,27 +123,31 @@ static unsigned long clk_pxa3xx_hsio_getrate(struct clk *clk)
return hsio_clk;
}

-static void clk_pxa3xx_cken_enable(struct clk *clk)
+static int clk_pxa3xx_cken_enable(struct clk *clk)
{
- unsigned long mask = 1ul << (clk->cken & 0x1f);
+ int cken = ((struct clk_cken_priv *)clk->priv)->cken;
+ unsigned long mask = 1ul << (cken & 0x1f);

local_irq_disable();

- if (clk->cken < 32)
+ if (cken < 32)
CKENA |= mask;
else
CKENB |= mask;

local_irq_enable();
+
+ return 0;
}

static void clk_pxa3xx_cken_disable(struct clk *clk)
{
- unsigned long mask = 1ul << (clk->cken & 0x1f);
+ int cken = ((struct clk_cken_priv *)clk->priv)->cken;
+ unsigned long mask = 1ul << (cken & 0x1f);

local_irq_disable();

- if (clk->cken < 32)
+ if (cken < 32)
CKENA &= ~mask;
else
CKENB &= ~mask;
@@ -151,55 +155,63 @@ static void clk_pxa3xx_cken_disable(struct clk *clk)
local_irq_enable();
}

-static const struct clkops clk_pxa3xx_cken_ops = {
- .enable = clk_pxa3xx_cken_enable,
- .disable = clk_pxa3xx_cken_disable,
-};
-
-static const struct clkops clk_pxa3xx_hsio_ops = {
- .enable = clk_pxa3xx_cken_enable,
- .disable = clk_pxa3xx_cken_disable,
- .getrate = clk_pxa3xx_hsio_getrate,
-};
-
-#define PXA3xx_CKEN(_name, _cken, _rate, _delay, _dev) \
+#define PXA3xx_CKEN(_name, _cken, _rate, _delay) \
{ \
.name = _name, \
- .dev = _dev, \
- .ops = &clk_pxa3xx_cken_ops, \
+ .enable = clk_pxa3xx_cken_enable, \
+ .disable = clk_pxa3xx_cken_disable, \
.rate = _rate, \
- .cken = CKEN_##_cken, \
.delay = _delay, \
+ .priv = &(struct clk_cken_priv) { \
+ .cken = CKEN_##_cken, \
+ }, \
}

-#define PXA3xx_CK(_name, _cken, _ops, _dev) \
+#define PXA3xx_CK(_name, _cken, _getrate) \
{ \
.name = _name, \
- .dev = _dev, \
- .ops = _ops, \
- .cken = CKEN_##_cken, \
+ .enable = clk_pxa3xx_cken_enable, \
+ .disable = clk_pxa3xx_cken_disable, \
+ .getrate = _getrate, \
+ .priv = &(struct clk_cken_priv) { \
+ .cken = CKEN_##_cken, \
+ }, \
}

static struct clk pxa3xx_clks[] = {
- PXA3xx_CK("LCDCLK", LCD, &clk_pxa3xx_hsio_ops, &pxa_device_fb.dev),
- PXA3xx_CK("CAMCLK", CAMERA, &clk_pxa3xx_hsio_ops, NULL),
+ PXA3xx_CK("LCDCLK", LCD, &clk_pxa3xx_hsio_getrate),
+ PXA3xx_CK("CAMCLK", CAMERA, &clk_pxa3xx_hsio_getrate),

- PXA3xx_CKEN("UARTCLK", FFUART, 14857000, 1, &pxa_device_ffuart.dev),
- PXA3xx_CKEN("UARTCLK", BTUART, 14857000, 1, &pxa_device_btuart.dev),
- PXA3xx_CKEN("UARTCLK", STUART, 14857000, 1, NULL),
+ PXA3xx_CKEN("FFUARTCLK", FFUART, 14857000, 1),
+ PXA3xx_CKEN("BTUARTCLK", BTUART, 14857000, 1),
+ PXA3xx_CKEN("STUARTCLK", STUART, 14857000, 1),

- PXA3xx_CKEN("I2CCLK", I2C, 32842000, 0, &pxa_device_i2c.dev),
- PXA3xx_CKEN("UDCCLK", UDC, 48000000, 5, &pxa_device_udc.dev),
- PXA3xx_CKEN("USBCLK", USBH, 48000000, 0, &pxa27x_device_ohci.dev),
+ PXA3xx_CKEN("I2CCLK", I2C, 32842000, 0),
+ PXA3xx_CKEN("UDCCLK", UDC, 48000000, 5),
+ PXA3xx_CKEN("USBCLK", USBH, 48000000, 0),

- PXA3xx_CKEN("SSPCLK", SSP1, 13000000, 0, &pxa27x_device_ssp1.dev),
- PXA3xx_CKEN("SSPCLK", SSP2, 13000000, 0, &pxa27x_device_ssp2.dev),
- PXA3xx_CKEN("SSPCLK", SSP3, 13000000, 0, &pxa27x_device_ssp3.dev),
- PXA3xx_CKEN("SSPCLK", SSP4, 13000000, 0, &pxa3xx_device_ssp4.dev),
+ PXA3xx_CKEN("SSP1CLK", SSP1, 13000000, 0),
+ PXA3xx_CKEN("SSP2CLK", SSP2, 13000000, 0),
+ PXA3xx_CKEN("SSP3CLK", SSP3, 13000000, 0),
+ PXA3xx_CKEN("SSP4CLK", SSP4, 13000000, 0),
+
+ PXA3xx_CKEN("MMC1CLK", MMC1, 19500000, 0),
+ PXA3xx_CKEN("MMC2CLK", MMC2, 19500000, 0),
+ PXA3xx_CKEN("MMC3CLK", MMC3, 19500000, 0),
+};

- PXA3xx_CKEN("MMCCLK", MMC1, 19500000, 0, &pxa_device_mci.dev),
- PXA3xx_CKEN("MMCCLK", MMC2, 19500000, 0, &pxa3xx_device_mci2.dev),
- PXA3xx_CKEN("MMCCLK", MMC3, 19500000, 0, &pxa3xx_device_mci3.dev),
+static struct clk_function __initdata pxa3xx_clk_funcs[] = {
+ CLK_FUNC("FFUARTCLK", "UARTCLK", clk_dev_can_get, &pxa_device_ffuart.dev, clk_dev_format),
+ CLK_FUNC("BTUARTCLK", "UARTCLK", clk_dev_can_get, &pxa_device_btuart.dev, clk_dev_format),
+ CLK_FUNC("STUARTCLK", "UARTCLK", clk_dev_can_get, &pxa_device_stuart.dev, clk_dev_format),
+ CLK_FUNC("STUARTCLK", "SIRCLK", NULL, NULL, NULL),
+ CLK_FUNC("SSP1CLK", "SSPCLK", clk_dev_can_get, &pxa27x_device_ssp1.dev, clk_dev_format),
+ CLK_FUNC("SSP2CLK", "SSPCLK", clk_dev_can_get, &pxa27x_device_ssp2.dev, clk_dev_format),
+ CLK_FUNC("SSP3CLK", "SSPCLK", clk_dev_can_get, &pxa27x_device_ssp3.dev, clk_dev_format),
+ CLK_FUNC("SSP4CLK", "SSPCLK", clk_dev_can_get, &pxa3xx_device_ssp4.dev, clk_dev_format),
+ CLK_FUNC("MMC1CLK", "MMCCLK", clk_dev_can_get, &pxa_device_mci.dev, clk_dev_format),
+ CLK_FUNC("MMC2CLK", "MMCCLK", clk_dev_can_get, &pxa3xx_device_mci2.dev, clk_dev_format),
+ CLK_FUNC("MMC3CLK", "MMCCLK", clk_dev_can_get, &pxa3xx_device_mci3.dev, clk_dev_format),
};

#ifdef CONFIG_PM
@@ -458,6 +470,7 @@ static int __init pxa3xx_init(void)

if (cpu_is_pxa3xx()) {
clks_register(pxa3xx_clks, ARRAY_SIZE(pxa3xx_clks));
+ clk_alloc_functions(pxa3xx_clk_funcs, ARRAY_SIZE(pxa3xx_clk_funcs));

if ((ret = pxa_init_dma(32)))
return ret;
--
1.5.3.8


--
With best wishes
Dmitry

2008-02-02 23:01:51

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH 4/5] Use correct clock for IrDA on pxa

Signed-off-by: Dmitry Baryshkov <[email protected]>
---
drivers/net/irda/pxaficp_ir.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c
index 8c09344..36d2ec0 100644
--- a/drivers/net/irda/pxaficp_ir.c
+++ b/drivers/net/irda/pxaficp_ir.c
@@ -814,7 +814,7 @@ static int pxa_irda_probe(struct platform_device *pdev)
si->dev = &pdev->dev;
si->pdata = pdev->dev.platform_data;

- si->sir_clk = clk_get(&pdev->dev, "UARTCLK");
+ si->sir_clk = clk_get(&pdev->dev, "SIRCLK");
si->fir_clk = clk_get(&pdev->dev, "FICPCLK");
if (IS_ERR(si->sir_clk) || IS_ERR(si->fir_clk)) {
err = PTR_ERR(IS_ERR(si->sir_clk) ? si->sir_clk : si->fir_clk);
--
1.5.3.8


--
With best wishes
Dmitry

2008-02-02 23:02:20

by Dmitry Baryshkov

[permalink] [raw]
Subject: [PATCH 5/5] Use clocklib for sa1100 sub-arch.

Signed-off-by: Dmitry Baryshkov <[email protected]>
---
arch/arm/Kconfig | 1 +
arch/arm/mach-sa1100/clock.c | 95 ++---------------------------------------
2 files changed, 6 insertions(+), 90 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 45c1790..cd8f792 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -385,6 +385,7 @@ config ARCH_SA1100
select ARCH_MTD_XIP
select GENERIC_GPIO
select GENERIC_TIME
+ select HAVE_CLOCK_LIB
help
Support for StrongARM 11x0 based boards.

diff --git a/arch/arm/mach-sa1100/clock.c b/arch/arm/mach-sa1100/clock.c
index fc97fe5..6b3cc51 100644
--- a/arch/arm/mach-sa1100/clock.c
+++ b/arch/arm/mach-sa1100/clock.c
@@ -8,83 +8,13 @@
#include <linux/err.h>
#include <linux/string.h>
#include <linux/clk.h>
+#include <linux/clklib.h>
#include <linux/spinlock.h>
#include <linux/mutex.h>

#include <asm/hardware.h>

-/*
- * Very simple clock implementation - we only have one clock to
- * deal with at the moment, so we only match using the "name".
- */
-struct clk {
- struct list_head node;
- unsigned long rate;
- const char *name;
- unsigned int enabled;
- void (*enable)(void);
- void (*disable)(void);
-};
-
-static LIST_HEAD(clocks);
-static DEFINE_MUTEX(clocks_mutex);
-static DEFINE_SPINLOCK(clocks_lock);
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
- struct clk *p, *clk = ERR_PTR(-ENOENT);
-
- mutex_lock(&clocks_mutex);
- list_for_each_entry(p, &clocks, node) {
- if (strcmp(id, p->name) == 0) {
- clk = p;
- break;
- }
- }
- mutex_unlock(&clocks_mutex);
-
- return clk;
-}
-EXPORT_SYMBOL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_put);
-
-int clk_enable(struct clk *clk)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&clocks_lock, flags);
- if (clk->enabled++ == 0)
- clk->enable();
- spin_unlock_irqrestore(&clocks_lock, flags);
- return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
- unsigned long flags;
-
- WARN_ON(clk->enabled == 0);
-
- spin_lock_irqsave(&clocks_lock, flags);
- if (--clk->enabled == 0)
- clk->disable();
- spin_unlock_irqrestore(&clocks_lock, flags);
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
- return clk->rate;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-
-static void clk_gpio27_enable(void)
+static int clk_gpio27_enable(struct clk *clk)
{
/*
* First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
@@ -93,9 +23,11 @@ static void clk_gpio27_enable(void)
GAFR |= GPIO_32_768kHz;
GPDR |= GPIO_32_768kHz;
TUCR = TUCR_3_6864MHz;
+
+ return 0;
}

-static void clk_gpio27_disable(void)
+static void clk_gpio27_disable(struct clk *clk)
{
TUCR = 0;
GPDR &= ~GPIO_32_768kHz;
@@ -109,23 +41,6 @@ static struct clk clk_gpio27 = {
.disable = clk_gpio27_disable,
};

-int clk_register(struct clk *clk)
-{
- mutex_lock(&clocks_mutex);
- list_add(&clk->node, &clocks);
- mutex_unlock(&clocks_mutex);
- return 0;
-}
-EXPORT_SYMBOL(clk_register);
-
-void clk_unregister(struct clk *clk)
-{
- mutex_lock(&clocks_mutex);
- list_del(&clk->node);
- mutex_unlock(&clocks_mutex);
-}
-EXPORT_SYMBOL(clk_unregister);
-
static int __init clk_init(void)
{
clk_register(&clk_gpio27);
--
1.5.3.8


--
With best wishes
Dmitry