浏览代码

[ARM] 5549/1: Add clock api for w90p910 platform.

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>
wanzongshun 16 年之前
父节点
当前提交
0e4a34bb65

+ 1 - 0
arch/arm/Kconfig

@@ -490,6 +490,7 @@ config ARCH_W90X900
 	select CPU_ARM926T
 	select CPU_ARM926T
 	select ARCH_REQUIRE_GPIOLIB
 	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_GPIO
 	select GENERIC_GPIO
+	select COMMON_CLKDEV
 	help
 	help
 		Support for Nuvoton (Winbond logic dept.) ARM9 processor,You
 		Support for Nuvoton (Winbond logic dept.) ARM9 processor,You
 		can login www.mcuos.com or www.nuvoton.com to know more.
 		can login www.mcuos.com or www.nuvoton.com to know more.

+ 1 - 1
arch/arm/mach-w90x900/Makefile

@@ -4,7 +4,7 @@
 
 
 # Object file lists.
 # 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
 # W90X900 CPU support files
 
 

+ 77 - 0
arch/arm/mach-w90x900/clock.c

@@ -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]);
+}

+ 36 - 0
arch/arm/mach-w90x900/clock.h

@@ -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,		\
+	}
+

+ 1 - 1
arch/arm/mach-w90x900/cpu.h

@@ -41,7 +41,7 @@ struct sys_timer;
 extern void w90x900_init_irq(void);
 extern void w90x900_init_irq(void);
 extern void w90p910_init_io(struct map_desc *mach_desc, int size);
 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_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 void w90p910_map_io(struct map_desc *mach_desc, int size);
 extern struct platform_device w90p910_serial_device;
 extern struct platform_device w90p910_serial_device;
 extern struct sys_timer w90x900_timer;
 extern struct sys_timer w90x900_timer;

+ 7 - 0
arch/arm/mach-w90x900/include/mach/clkdev.h

@@ -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

+ 1 - 1
arch/arm/mach-w90x900/mach-w90p910evb.c

@@ -247,7 +247,7 @@ static struct platform_device *w90p910evb_dev[] __initdata = {
 static void __init w90p910evb_map_io(void)
 static void __init w90p910evb_map_io(void)
 {
 {
 	w90p910_map_io(w90p910_iodesc, ARRAY_SIZE(w90p910_iodesc));
 	w90p910_map_io(w90p910_iodesc, ARRAY_SIZE(w90p910_iodesc));
-	w90p910_init_clocks(0);
+	w90p910_init_clocks();
 }
 }
 
 
 static void __init w90p910evb_init(void)
 static void __init w90p910evb_init(void)

+ 40 - 1
arch/arm/mach-w90x900/w90p910.c

@@ -34,6 +34,7 @@
 #include <mach/regs-serial.h>
 #include <mach/regs-serial.h>
 
 
 #include "cpu.h"
 #include "cpu.h"
+#include "clock.h"
 
 
 /* Initial IO mappings */
 /* Initial IO mappings */
 
 
@@ -52,6 +53,43 @@ static struct map_desc w90p910_iodesc[] __initdata = {
 	/*IODESC_ENT(LCD),*/
 	/*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 */
 /* Initial serial platform data */
 
 
 struct plat_serial8250_port w90p910_uart_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*/
 /*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)
 static int __init w90p910_init_cpu(void)