[ARM] 5549/1: Add clock api for w90p910 platform.
authorwanzongshun <mcuos.com@gmail.com>
Wed, 10 Jun 2009 14:50:44 +0000 (15:50 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 11 Jun 2009 13:45:18 +0000 (14:45 +0100)
Add clock api for w90p910 platform.

Signed-off-by: Wan ZongShun <mcuos.com@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/Kconfig
arch/arm/mach-w90x900/Makefile
arch/arm/mach-w90x900/clock.c [new file with mode: 0644]
arch/arm/mach-w90x900/clock.h [new file with mode: 0644]
arch/arm/mach-w90x900/cpu.h
arch/arm/mach-w90x900/include/mach/clkdev.h [new file with mode: 0644]
arch/arm/mach-w90x900/mach-w90p910evb.c
arch/arm/mach-w90x900/w90p910.c

index 013993c..7d54494 100644 (file)
@@ -490,6 +490,7 @@ config ARCH_W90X900
        select CPU_ARM926T
        select ARCH_REQUIRE_GPIOLIB
        select GENERIC_GPIO
+       select COMMON_CLKDEV
        help
                Support for Nuvoton (Winbond logic dept.) ARM9 processor,You
                can login www.mcuos.com or www.nuvoton.com to know more.
index 6287268..d50c94f 100644 (file)
@@ -4,7 +4,7 @@
 
 # Object file lists.
 
-obj-y                          := irq.o time.o mfp-w90p910.o gpio.o
+obj-y                          := irq.o time.o mfp-w90p910.o gpio.o clock.o
 
 # W90X900 CPU support files
 
diff --git a/arch/arm/mach-w90x900/clock.c b/arch/arm/mach-w90x900/clock.c
new file mode 100644 (file)
index 0000000..f420613
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * linux/arch/arm/mach-w90x900/clock.c
+ *
+ * Copyright (c) 2008 Nuvoton technology corporation
+ *
+ * Wan ZongShun <mcuos.com@gmail.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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/clk.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+
+#include "clock.h"
+
+static DEFINE_SPINLOCK(clocks_lock);
+
+int clk_enable(struct clk *clk)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&clocks_lock, flags);
+       if (clk->enabled++ == 0)
+               (clk->enable)(clk, 1);
+       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->enable)(clk, 0);
+       spin_unlock_irqrestore(&clocks_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable);
+
+void w90x900_clk_enable(struct clk *clk, int enable)
+{
+       unsigned int clocks = clk->cken;
+       unsigned long clken;
+
+       clken = __raw_readl(W90X900_VA_CLKPWR);
+
+       if (enable)
+               clken |= clocks;
+       else
+               clken &= ~clocks;
+
+       __raw_writel(clken, W90X900_VA_CLKPWR);
+}
+
+void clks_register(struct clk_lookup *clks, size_t num)
+{
+       int i;
+
+       for (i = 0; i < num; i++)
+               clkdev_add(&clks[i]);
+}
diff --git a/arch/arm/mach-w90x900/clock.h b/arch/arm/mach-w90x900/clock.h
new file mode 100644 (file)
index 0000000..4f27bda
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * linux/arch/arm/mach-w90x900/clock.h
+ *
+ * Copyright (c) 2008 Nuvoton technology corporation
+ *
+ * Wan ZongShun <mcuos.com@gmail.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.
+ */
+
+#include <asm/clkdev.h>
+
+void w90x900_clk_enable(struct clk *clk, int enable);
+void clks_register(struct clk_lookup *clks, size_t num);
+
+struct clk {
+       unsigned long           cken;
+       unsigned int            enabled;
+       void                    (*enable)(struct clk *, int enable);
+};
+
+#define DEFINE_CLK(_name, _ctrlbit)                    \
+struct clk clk_##_name = {                             \
+               .enable = w90x900_clk_enable,           \
+               .cken   = (1 << _ctrlbit),              \
+       }
+
+#define DEF_CLKLOOK(_clk, _devname, _conname)          \
+       {                                               \
+               .clk            = _clk,                 \
+               .dev_id         = _devname,             \
+               .con_id         = _conname,             \
+       }
+
index de29ddc..57b5dba 100644 (file)
@@ -41,7 +41,7 @@ struct sys_timer;
 extern void w90x900_init_irq(void);
 extern void w90p910_init_io(struct map_desc *mach_desc, int size);
 extern void w90p910_init_uarts(struct w90x900_uartcfg *cfg, int no);
-extern void w90p910_init_clocks(int xtal);
+extern void w90p910_init_clocks(void);
 extern void w90p910_map_io(struct map_desc *mach_desc, int size);
 extern struct platform_device w90p910_serial_device;
 extern struct sys_timer w90x900_timer;
diff --git a/arch/arm/mach-w90x900/include/mach/clkdev.h b/arch/arm/mach-w90x900/include/mach/clkdev.h
new file mode 100644 (file)
index 0000000..04b37a8
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __ASM_MACH_CLKDEV_H
+#define __ASM_MACH_CLKDEV_H
+
+#define __clk_get(clk) ({ 1; })
+#define __clk_put(clk) do { } while (0)
+
+#endif
index 1968ed4..7a62bd3 100644 (file)
@@ -247,7 +247,7 @@ static struct platform_device *w90p910evb_dev[] __initdata = {
 static void __init w90p910evb_map_io(void)
 {
        w90p910_map_io(w90p910_iodesc, ARRAY_SIZE(w90p910_iodesc));
-       w90p910_init_clocks(0);
+       w90p910_init_clocks();
 }
 
 static void __init w90p910evb_init(void)
index 87214b8..1c97e49 100644 (file)
@@ -34,6 +34,7 @@
 #include <mach/regs-serial.h>
 
 #include "cpu.h"
+#include "clock.h"
 
 /* Initial IO mappings */
 
@@ -52,6 +53,43 @@ static struct map_desc w90p910_iodesc[] __initdata = {
        /*IODESC_ENT(LCD),*/
 };
 
+/* Initial clock declarations. */
+static DEFINE_CLK(lcd, 0);
+static DEFINE_CLK(audio, 1);
+static DEFINE_CLK(fmi, 4);
+static DEFINE_CLK(dmac, 5);
+static DEFINE_CLK(atapi, 6);
+static DEFINE_CLK(emc, 7);
+static DEFINE_CLK(usbd, 8);
+static DEFINE_CLK(usbh, 9);
+static DEFINE_CLK(g2d, 10);;
+static DEFINE_CLK(pwm, 18);
+static DEFINE_CLK(ps2, 24);
+static DEFINE_CLK(kpi, 25);
+static DEFINE_CLK(wdt, 26);
+static DEFINE_CLK(gdma, 27);
+static DEFINE_CLK(adc, 28);
+static DEFINE_CLK(usi, 29);
+
+static struct clk_lookup w90p910_clkregs[] = {
+       DEF_CLKLOOK(&clk_lcd, "w90p910-lcd", NULL),
+       DEF_CLKLOOK(&clk_audio, "w90p910-audio", NULL),
+       DEF_CLKLOOK(&clk_fmi, "w90p910-fmi", NULL),
+       DEF_CLKLOOK(&clk_dmac, "w90p910-dmac", NULL),
+       DEF_CLKLOOK(&clk_atapi, "w90p910-atapi", NULL),
+       DEF_CLKLOOK(&clk_emc, "w90p910-emc", NULL),
+       DEF_CLKLOOK(&clk_usbd, "w90p910-usbd", NULL),
+       DEF_CLKLOOK(&clk_usbh, "w90p910-usbh", NULL),
+       DEF_CLKLOOK(&clk_g2d, "w90p910-g2d", NULL),
+       DEF_CLKLOOK(&clk_pwm, "w90p910-pwm", NULL),
+       DEF_CLKLOOK(&clk_ps2, "w90p910-ps2", NULL),
+       DEF_CLKLOOK(&clk_kpi, "w90p910-kpi", NULL),
+       DEF_CLKLOOK(&clk_wdt, "w90p910-wdt", NULL),
+       DEF_CLKLOOK(&clk_gdma, "w90p910-gdma", NULL),
+       DEF_CLKLOOK(&clk_adc, "w90p910-adc", NULL),
+       DEF_CLKLOOK(&clk_usi, "w90p910-usi", NULL),
+};
+
 /* Initial serial platform data */
 
 struct plat_serial8250_port w90p910_uart_data[] = {
@@ -81,8 +119,9 @@ void __init w90p910_map_io(struct map_desc *mach_desc, int mach_size)
 
 /*Init W90P910 clock*/
 
-void __init w90p910_init_clocks(int xtal)
+void __init w90p910_init_clocks(void)
 {
+       clks_register(w90p910_clkregs, ARRAY_SIZE(w90p910_clkregs));
 }
 
 static int __init w90p910_init_cpu(void)