linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] ARM: vexpress: Check master site in daughterboard's sysctl operations
@ 2012-06-08 12:50 Pawel Moll
  2012-06-08 12:50 ` [PATCH 2/2] ARM: vexpress: Initial common clock support Pawel Moll
  2012-06-12  8:58 ` [PATCH 1/2] ARM: vexpress: Check master site in daughterboard's sysctl operations Jon Medhurst (Tixy)
  0 siblings, 2 replies; 6+ messages in thread
From: Pawel Moll @ 2012-06-08 12:50 UTC (permalink / raw)
  To: linux-arm-kernel

With recent enough motherboard firmware, core tile can be fitted
in either of the two daughterboard sites. The non-DT tile code for
V2P-CA9 did not check that when configuring DVI output nor setting
CLCD pixel clock.

Fixed now, providing "get master site" API in motherboard's code.

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
 arch/arm/mach-vexpress/ct-ca9x4.c                 |   15 ++++++++++++---
 arch/arm/mach-vexpress/include/mach/motherboard.h |    9 ++++++---
 arch/arm/mach-vexpress/v2m.c                      |   12 +++++++++---
 3 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index c65cc3b..11cb248 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -66,8 +66,15 @@ static void __init ct_ca9x4_init_irq(void)
 
 static void ct_ca9x4_clcd_enable(struct clcd_fb *fb)
 {
-	v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0);
-	v2m_cfg_write(SYS_CFG_DVIMODE | SYS_CFG_SITE_DB1, 2);
+	u32 site = v2m_get_master_site();
+
+	/*
+	 * Old firmware was using the "site" component of the command
+	 * to control the DVI muxer (while it should be always 0 ie. MB).
+	 * Newer firmware uses the data register. Keep both for compatibility.
+	 */
+	v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE(site), site);
+	v2m_cfg_write(SYS_CFG_DVIMODE, 2);
 }
 
 static int ct_ca9x4_clcd_setup(struct clcd_fb *fb)
@@ -112,7 +119,9 @@ static long ct_round(struct clk *clk, unsigned long rate)
 
 static int ct_set(struct clk *clk, unsigned long rate)
 {
-	return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_DB1 | 1, rate);
+	u32 site = v2m_get_master_site();
+
+	return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(site) | 1, rate);
 }
 
 static const struct clk_ops osc1_clk_ops = {
diff --git a/arch/arm/mach-vexpress/include/mach/motherboard.h b/arch/arm/mach-vexpress/include/mach/motherboard.h
index 31a9289..f004ec9 100644
--- a/arch/arm/mach-vexpress/include/mach/motherboard.h
+++ b/arch/arm/mach-vexpress/include/mach/motherboard.h
@@ -104,9 +104,10 @@
 #define SYS_CFG_REBOOT		(9 << 20)
 #define SYS_CFG_DVIMODE		(11 << 20)
 #define SYS_CFG_POWER		(12 << 20)
-#define SYS_CFG_SITE_MB		(0 << 16)
-#define SYS_CFG_SITE_DB1	(1 << 16)
-#define SYS_CFG_SITE_DB2	(2 << 16)
+#define SYS_CFG_SITE(n)		((n) << 16)
+#define SYS_CFG_SITE_MB		0
+#define SYS_CFG_SITE_DB1	1
+#define SYS_CFG_SITE_DB2	2
 #define SYS_CFG_STACK(n)	((n) << 12)
 
 #define SYS_CFG_ERR		(1 << 1)
@@ -122,6 +123,8 @@ void v2m_flags_set(u32 data);
 #define SYS_MISC_MASTERSITE	(1 << 14)
 #define SYS_PROCIDx_HBI_MASK	0xfff
 
+int v2m_get_master_site(void);
+
 /*
  * Core tile IDs
  */
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index fde26ad..aa6f9a6 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -147,6 +147,13 @@ void __init v2m_flags_set(u32 data)
 	writel(data, v2m_sysreg_base + V2M_SYS_FLAGSSET);
 }
 
+int __init v2m_get_master_site(void)
+{
+	u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC);
+
+	return misc & SYS_MISC_MASTERSITE ? SYS_CFG_SITE_DB2 : SYS_CFG_SITE_DB1;
+}
+
 
 static struct resource v2m_pcie_i2c_resource = {
 	.start	= V2M_SERIAL_BUS_PCI,
@@ -413,7 +420,6 @@ static void v2m_restart(char str, const char *cmd)
 	if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE_MB, 0))
 		printk(KERN_EMERG "Unable to reboot\n");
 }
-
 struct ct_desc *ct_desc;
 
 static struct ct_desc *ct_descs[] __initdata = {
@@ -605,8 +611,8 @@ void __init v2m_dt_init_early(void)
 
 	/* Confirm board type against DT property, if available */
 	if (of_property_read_u32(allnodes, "arm,hbi", &dt_hbi) == 0) {
-		u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC);
-		u32 id = readl(v2m_sysreg_base + (misc & SYS_MISC_MASTERSITE ?
+		int site = v2m_get_master_site();
+		u32 id = readl(v2m_sysreg_base + (site == SYS_CFG_SITE_DB2 ?
 				V2M_SYS_PROCID1 : V2M_SYS_PROCID0));
 		u32 hbi = id & SYS_PROCIDx_HBI_MASK;
 
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 2/2] ARM: vexpress: Initial common clock support
  2012-06-08 12:50 [PATCH 1/2] ARM: vexpress: Check master site in daughterboard's sysctl operations Pawel Moll
@ 2012-06-08 12:50 ` Pawel Moll
  2012-06-13 10:07   ` Jon Medhurst (Tixy)
  2012-06-12  8:58 ` [PATCH 1/2] ARM: vexpress: Check master site in daughterboard's sysctl operations Jon Medhurst (Tixy)
  1 sibling, 1 reply; 6+ messages in thread
From: Pawel Moll @ 2012-06-08 12:50 UTC (permalink / raw)
  To: linux-arm-kernel

This patch makes Versatile Express use the common clock framework
instead of the plat-versatile implementation (which remains intact
for mach-versatile and mach-realview sake).

It defines clock provider for VE's OSCs (clock generators) and
registers all required fixed and variable clock sources (for both
motherboard and core tile).

Signed-off-by: Pawel Moll <pawel.moll@arm.com>
---
 arch/arm/Kconfig                                  |    2 +-
 arch/arm/mach-vexpress/ct-ca9x4.c                 |   55 +----
 arch/arm/mach-vexpress/include/mach/clkdev.h      |   15 --
 arch/arm/mach-vexpress/include/mach/motherboard.h |   20 ++
 arch/arm/mach-vexpress/v2m.c                      |  253 +++++++++------------
 arch/arm/plat-versatile/Kconfig                   |    5 +
 arch/arm/plat-versatile/Makefile                  |    2 +-
 7 files changed, 150 insertions(+), 202 deletions(-)
 delete mode 100644 arch/arm/mach-vexpress/include/mach/clkdev.h

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 84449dd..6f3370e 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -306,7 +306,7 @@ config ARCH_VEXPRESS
 	select ARM_AMBA
 	select ARM_TIMER_SP804
 	select CLKDEV_LOOKUP
-	select HAVE_MACH_CLKDEV
+	select COMMON_CLK
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
 	select HAVE_PATA_PLATFORM
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 11cb248..3ef3fda 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -111,48 +111,22 @@ static struct amba_device *ct_ca9x4_amba_devs[] __initdata = {
 	&gpio_device,
 };
 
+static struct v2m_osc ct_osc1 = {
+	.osc = 1,
+	.rate_min = 10000000,
+	.rate_max = 80000000,
+	.rate_default = 23750000,
+};
 
-static long ct_round(struct clk *clk, unsigned long rate)
-{
-	return rate;
-}
-
-static int ct_set(struct clk *clk, unsigned long rate)
+static void __init ct_ca9x4_init_clk(void)
 {
-	u32 site = v2m_get_master_site();
+	struct clk *clk;
 
-	return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(site) | 1, rate);
+	ct_osc1.site = v2m_get_master_site();
+	clk = v2m_osc_register("ct:osc1", &ct_osc1);
+	clk_register_clkdev(clk, NULL, "ct:clcd");
 }
 
-static const struct clk_ops osc1_clk_ops = {
-	.round	= ct_round,
-	.set	= ct_set,
-};
-
-static struct clk osc1_clk = {
-	.ops	= &osc1_clk_ops,
-	.rate	= 24000000,
-};
-
-static struct clk ct_sp804_clk = {
-	.rate	= 1000000,
-};
-
-static struct clk_lookup lookups[] = {
-	{	/* CLCD */
-		.dev_id		= "ct:clcd",
-		.clk		= &osc1_clk,
-	}, {	/* SP804 timers */
-		.dev_id		= "sp804",
-		.con_id		= "ct-timer0",
-		.clk		= &ct_sp804_clk,
-	}, {	/* SP804 timers */
-		.dev_id		= "sp804",
-		.con_id		= "ct-timer1",
-		.clk		= &ct_sp804_clk,
-	},
-};
-
 static struct resource pmu_resources[] = {
 	[0] = {
 		.start	= IRQ_CT_CA9X4_PMU_CPU0,
@@ -183,11 +157,6 @@ static struct platform_device pmu_device = {
 	.resource	= pmu_resources,
 };
 
-static void __init ct_ca9x4_init_early(void)
-{
-	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-}
-
 static void __init ct_ca9x4_init(void)
 {
 	int i;
@@ -243,8 +212,8 @@ struct ct_desc ct_ca9x4_desc __initdata = {
 	.id		= V2M_CT_ID_CA9,
 	.name		= "CA9x4",
 	.map_io		= ct_ca9x4_map_io,
-	.init_early	= ct_ca9x4_init_early,
 	.init_irq	= ct_ca9x4_init_irq,
+	.init_clk	= ct_ca9x4_init_clk,
 	.init_tile	= ct_ca9x4_init,
 #ifdef CONFIG_SMP
 	.init_cpu_map	= ct_ca9x4_init_cpu_map,
diff --git a/arch/arm/mach-vexpress/include/mach/clkdev.h b/arch/arm/mach-vexpress/include/mach/clkdev.h
deleted file mode 100644
index 3f8307d..0000000
--- a/arch/arm/mach-vexpress/include/mach/clkdev.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#include <plat/clock.h>
-
-struct clk {
-	const struct clk_ops	*ops;
-	unsigned long		rate;
-	const struct icst_params *params;
-};
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
diff --git a/arch/arm/mach-vexpress/include/mach/motherboard.h b/arch/arm/mach-vexpress/include/mach/motherboard.h
index f004ec9..2762263 100644
--- a/arch/arm/mach-vexpress/include/mach/motherboard.h
+++ b/arch/arm/mach-vexpress/include/mach/motherboard.h
@@ -1,6 +1,8 @@
 #ifndef __MACH_MOTHERBOARD_H
 #define __MACH_MOTHERBOARD_H
 
+#include <linux/clk-provider.h>
+
 /*
  * Physical addresses, offset from V2M_PA_CS0-3
  */
@@ -138,6 +140,7 @@ struct ct_desc {
 	void			(*map_io)(void);
 	void			(*init_early)(void);
 	void			(*init_irq)(void);
+	void			(*init_clk)(void);
 	void			(*init_tile)(void);
 #ifdef CONFIG_SMP
 	void			(*init_cpu_map)(void);
@@ -147,4 +150,21 @@ struct ct_desc {
 
 extern struct ct_desc *ct_desc;
 
+/*
+ * OSC clock provider
+ */
+struct v2m_osc {
+	struct clk_hw hw;
+	u8 site; /* 0 = motherboard, 1 = site 1, 2 = site 2 */
+	u8 stack; /* board stack position */
+	u16 osc;
+	unsigned long rate_min;
+	unsigned long rate_max;
+	unsigned long rate_default;
+};
+
+#define to_v2m_osc(osc) container_of(osc, struct v2m_osc, hw)
+
+struct clk *v2m_osc_register(const char *name, struct v2m_osc *osc);
+
 #endif
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index aa6f9a6..e1e2415 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -16,6 +16,7 @@
 #include <linux/spinlock.h>
 #include <linux/usb/isp1760.h>
 #include <linux/clkdev.h>
+#include <linux/clk-provider.h>
 #include <linux/mtd/physmap.h>
 
 #include <asm/arch_timer.h>
@@ -81,16 +82,6 @@ static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
 	sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0");
 }
 
-static void __init v2m_timer_init(void)
-{
-	v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K));
-	v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
-}
-
-static struct sys_timer v2m_timer = {
-	.init	= v2m_timer_init,
-};
-
 
 static DEFINE_SPINLOCK(v2m_cfg_lock);
 
@@ -326,86 +317,135 @@ static struct amba_device *v2m_amba_devs[] __initdata = {
 };
 
 
-static long v2m_osc_round(struct clk *clk, unsigned long rate)
+static unsigned long v2m_osc_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct v2m_osc *osc = to_v2m_osc(hw);
+
+	return !parent_rate ? osc->rate_default : parent_rate;
+}
+
+static long v2m_osc_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *parent_rate)
 {
+	struct v2m_osc *osc = to_v2m_osc(hw);
+
+	if (WARN_ON(rate < osc->rate_min))
+		rate = osc->rate_min;
+
+	if (WARN_ON(rate > osc->rate_max))
+		rate = osc->rate_max;
+
 	return rate;
 }
 
-static int v2m_osc1_set(struct clk *clk, unsigned long rate)
+static int v2m_osc_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
 {
-	return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_MB | 1, rate);
+	struct v2m_osc *osc = to_v2m_osc(hw);
+
+	v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(osc->site) |
+		SYS_CFG_STACK(osc->stack) | osc->osc, rate);
+
+	return 0;
 }
 
-static const struct clk_ops osc1_clk_ops = {
-	.round	= v2m_osc_round,
-	.set	= v2m_osc1_set,
+static struct clk_ops v2m_osc_ops = {
+	.recalc_rate = v2m_osc_recalc_rate,
+	.round_rate = v2m_osc_round_rate,
+	.set_rate = v2m_osc_set_rate,
 };
 
-static struct clk osc1_clk = {
-	.ops	= &osc1_clk_ops,
-	.rate	= 24000000,
+struct clk * __init v2m_osc_register(const char *name, struct v2m_osc *osc)
+{
+	struct clk_init_data init;
+
+	WARN_ON(osc->site > 2);
+	WARN_ON(osc->stack > 15);
+	WARN_ON(osc->osc > 4095);
+
+	init.name = name;
+	init.ops = &v2m_osc_ops;
+	init.flags = CLK_IS_ROOT;
+	init.num_parents = 0;
+
+	osc->hw.init = &init;
+
+	return clk_register(NULL, &osc->hw);
+}
+
+static struct v2m_osc v2m_mb_osc1 = {
+	.site = SYS_CFG_SITE_MB,
+	.osc = 1,
+	.rate_min = 23750000,
+	.rate_max = 63500000,
+	.rate_default = 23750000,
 };
 
-static struct clk osc2_clk = {
-	.rate	= 24000000,
+static const char *v2m_ref_clk_periphs[] __initconst = {
+	"mb:wdt",	"1000f000.wdt",	"1c0f0000.wdt",	/* SP805 WDT */
 };
 
-static struct clk v2m_sp804_clk = {
-	.rate	= 1000000,
+static const char *v2m_osc1_periphs[] __initconst = {
+	"mb:clcd",	"1001f000.clcd", "1c1f0000.clcd",	/* PL111 CLCD */
 };
 
-static struct clk v2m_ref_clk = {
-	.rate   = 32768,
+static const char *v2m_osc2_periphs[] __initconst = {
+	"mb:mmci",	"10005000.mmci", "1c050000.mmci",	/* PL180 MMCI */
+	"mb:kmi0",	"10006000.kmi",	"1c060000.kmi",	/* PL050 KMI0 */
+	"mb:kmi1",	"10007000.kmi",	"1c070000.kmi",	/* PL050 KMI1 */
+	"mb:uart0", "10009000.uart", "1c090000.uart",	/* PL011 UART0 */
+	"mb:uart1", "1000a000.uart", "1c0a0000.uart",	/* PL011 UART1 */
+	"mb:uart2", "1000b000.uart", "1c0b0000.uart",	/* PL011 UART2 */
+	"mb:uart3", "1000c000.uart", "1c0c0000.uart",	/* PL011 UART3 */
 };
 
-static struct clk dummy_apb_pclk;
-
-static struct clk_lookup v2m_lookups[] = {
-	{	/* AMBA bus clock */
-		.con_id		= "apb_pclk",
-		.clk		= &dummy_apb_pclk,
-	}, {	/* UART0 */
-		.dev_id		= "mb:uart0",
-		.clk		= &osc2_clk,
-	}, {	/* UART1 */
-		.dev_id		= "mb:uart1",
-		.clk		= &osc2_clk,
-	}, {	/* UART2 */
-		.dev_id		= "mb:uart2",
-		.clk		= &osc2_clk,
-	}, {	/* UART3 */
-		.dev_id		= "mb:uart3",
-		.clk		= &osc2_clk,
-	}, {	/* KMI0 */
-		.dev_id		= "mb:kmi0",
-		.clk		= &osc2_clk,
-	}, {	/* KMI1 */
-		.dev_id		= "mb:kmi1",
-		.clk		= &osc2_clk,
-	}, {	/* MMC0 */
-		.dev_id		= "mb:mmci",
-		.clk		= &osc2_clk,
-	}, {	/* CLCD */
-		.dev_id		= "mb:clcd",
-		.clk		= &osc1_clk,
-	}, {	/* SP805 WDT */
-		.dev_id		= "mb:wdt",
-		.clk		= &v2m_ref_clk,
-	}, {	/* SP804 timers */
-		.dev_id		= "sp804",
-		.con_id		= "v2m-timer0",
-		.clk		= &v2m_sp804_clk,
-	}, {	/* SP804 timers */
-		.dev_id		= "sp804",
-		.con_id		= "v2m-timer1",
-		.clk		= &v2m_sp804_clk,
-	},
+static void __init v2m_clk_init(void)
+{
+	struct clk *clk;
+	int i;
+
+	clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL,
+			CLK_IS_ROOT, 0);
+	WARN_ON(clk_register_clkdev(clk, "abp_pclk", NULL));
+
+	clk = clk_register_fixed_rate(NULL, "mb:ref_clk", NULL,
+			CLK_IS_ROOT, 32768);
+	for (i = 0; i < ARRAY_SIZE(v2m_ref_clk_periphs); i++)
+		WARN_ON(clk_register_clkdev(clk, NULL, v2m_ref_clk_periphs[i]));
+
+	clk = clk_register_fixed_rate(NULL, "mb:sp804_clk", NULL,
+			CLK_IS_ROOT, 1000000);
+	WARN_ON(clk_register_clkdev(clk, "v2m-timer0", "sp804"));
+	WARN_ON(clk_register_clkdev(clk, "v2m-timer1", "sp804"));
+
+	clk = v2m_osc_register("mb:osc1", &v2m_mb_osc1);
+	for (i = 0; i < ARRAY_SIZE(v2m_osc1_periphs); i++)
+		WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc1_periphs[i]));
+
+	clk = clk_register_fixed_rate(NULL, "mb:osc2", NULL,
+			CLK_IS_ROOT, 24000000);
+	for (i = 0; i < ARRAY_SIZE(v2m_osc2_periphs); i++)
+		WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc2_periphs[i]));
+}
+
+static void __init v2m_timer_init(void)
+{
+	v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K));
+	v2m_clk_init();
+	if (ct_desc->init_clk)
+		ct_desc->init_clk();
+	v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
+}
+
+static struct sys_timer v2m_timer = {
+	.init	= v2m_timer_init,
 };
 
 static void __init v2m_init_early(void)
 {
-	ct_desc->init_early();
-	clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups));
+	if (ct_desc->init_early)
+		ct_desc->init_early();
 	versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
 }
 
@@ -528,77 +568,6 @@ void __init v2m_dt_map_io(void)
 #endif
 }
 
-static struct clk_lookup v2m_dt_lookups[] = {
-	{	/* AMBA bus clock */
-		.con_id		= "apb_pclk",
-		.clk		= &dummy_apb_pclk,
-	}, {	/* SP804 timers */
-		.dev_id		= "sp804",
-		.con_id		= "v2m-timer0",
-		.clk		= &v2m_sp804_clk,
-	}, {	/* SP804 timers */
-		.dev_id		= "sp804",
-		.con_id		= "v2m-timer1",
-		.clk		= &v2m_sp804_clk,
-	}, {	/* PL180 MMCI */
-		.dev_id		= "mb:mmci", /* 10005000.mmci */
-		.clk		= &osc2_clk,
-	}, {	/* PL050 KMI0 */
-		.dev_id		= "10006000.kmi",
-		.clk		= &osc2_clk,
-	}, {	/* PL050 KMI1 */
-		.dev_id		= "10007000.kmi",
-		.clk		= &osc2_clk,
-	}, {	/* PL011 UART0 */
-		.dev_id		= "10009000.uart",
-		.clk		= &osc2_clk,
-	}, {	/* PL011 UART1 */
-		.dev_id		= "1000a000.uart",
-		.clk		= &osc2_clk,
-	}, {	/* PL011 UART2 */
-		.dev_id		= "1000b000.uart",
-		.clk		= &osc2_clk,
-	}, {	/* PL011 UART3 */
-		.dev_id		= "1000c000.uart",
-		.clk		= &osc2_clk,
-	}, {	/* SP805 WDT */
-		.dev_id		= "1000f000.wdt",
-		.clk		= &v2m_ref_clk,
-	}, {	/* PL111 CLCD */
-		.dev_id		= "1001f000.clcd",
-		.clk		= &osc1_clk,
-	},
-	/* RS1 memory map */
-	{	/* PL180 MMCI */
-		.dev_id		= "mb:mmci", /* 1c050000.mmci */
-		.clk		= &osc2_clk,
-	}, {	/* PL050 KMI0 */
-		.dev_id		= "1c060000.kmi",
-		.clk		= &osc2_clk,
-	}, {	/* PL050 KMI1 */
-		.dev_id		= "1c070000.kmi",
-		.clk		= &osc2_clk,
-	}, {	/* PL011 UART0 */
-		.dev_id		= "1c090000.uart",
-		.clk		= &osc2_clk,
-	}, {	/* PL011 UART1 */
-		.dev_id		= "1c0a0000.uart",
-		.clk		= &osc2_clk,
-	}, {	/* PL011 UART2 */
-		.dev_id		= "1c0b0000.uart",
-		.clk		= &osc2_clk,
-	}, {	/* PL011 UART3 */
-		.dev_id		= "1c0c0000.uart",
-		.clk		= &osc2_clk,
-	}, {	/* SP805 WDT */
-		.dev_id		= "1c0f0000.wdt",
-		.clk		= &v2m_ref_clk,
-	}, {	/* PL111 CLCD */
-		.dev_id		= "1c1f0000.clcd",
-		.clk		= &osc1_clk,
-	},
-};
-
 void __init v2m_dt_init_early(void)
 {
 	struct device_node *node;
@@ -620,8 +589,6 @@ void __init v2m_dt_init_early(void)
 			pr_warning("vexpress: DT HBI (%x) is not matching "
 					"hardware (%x)!\n", dt_hbi, hbi);
 	}
-
-	clkdev_add_table(v2m_dt_lookups, ARRAY_SIZE(v2m_dt_lookups));
 }
 
 static  struct of_device_id vexpress_irq_match[] __initdata = {
@@ -643,6 +610,8 @@ static void __init v2m_dt_timer_init(void)
 	node = of_find_compatible_node(NULL, NULL, "arm,sp810");
 	v2m_sysctl_init(of_iomap(node, 0));
 
+	v2m_clk_init();
+
 	err = of_property_read_string(of_aliases, "arm,v2m_timer", &path);
 	if (WARN_ON(err))
 		return;
diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig
index 81ee7cc..4b9f4bf 100644
--- a/arch/arm/plat-versatile/Kconfig
+++ b/arch/arm/plat-versatile/Kconfig
@@ -1,5 +1,10 @@
 if PLAT_VERSATILE
 
+config PLAT_VERSATILE_CLOCK
+	bool
+	default y
+	depends on !COMMON_CLK
+
 config PLAT_VERSATILE_CLCD
 	bool
 
diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile
index a5cb194..272769a8 100644
--- a/arch/arm/plat-versatile/Makefile
+++ b/arch/arm/plat-versatile/Makefile
@@ -1,4 +1,4 @@
-obj-y	:= clock.o
+obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o
 obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
 obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o
 obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [PATCH 1/2] ARM: vexpress: Check master site in daughterboard's sysctl operations
  2012-06-08 12:50 [PATCH 1/2] ARM: vexpress: Check master site in daughterboard's sysctl operations Pawel Moll
  2012-06-08 12:50 ` [PATCH 2/2] ARM: vexpress: Initial common clock support Pawel Moll
@ 2012-06-12  8:58 ` Jon Medhurst (Tixy)
  2012-06-12  9:08   ` Pawel Moll
  2012-06-12 13:02   ` Jon Medhurst (Tixy)
  1 sibling, 2 replies; 6+ messages in thread
From: Jon Medhurst (Tixy) @ 2012-06-12  8:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2012-06-08 at 13:50 +0100, Pawel Moll wrote:
> With recent enough motherboard firmware, core tile can be fitted
> in either of the two daughterboard sites. The non-DT tile code for
> V2P-CA9 did not check that when configuring DVI output nor setting
> CLCD pixel clock.
> 
> Fixed now, providing "get master site" API in motherboard's code.
> 
> Signed-off-by: Pawel Moll <pawel.moll@arm.com>

This patch makes an Ubuntu boot always hang for me, about the time it
would switch to GUI mode, it's not very consistent unfortunately.

If I modify ct_ca9x4_clcd_enable() to replace "v2m_get_master_site()"
with "1" then boot is OK. Even though if I put code it to test the
return value from v2m_get_master_site() it shows it gives 1.

I am running stock Version 3 firmware on my vexpress.

I also have some comments about this patch, see inline comments below...

> ---
>  arch/arm/mach-vexpress/ct-ca9x4.c                 |   15 ++++++++++++---
>  arch/arm/mach-vexpress/include/mach/motherboard.h |    9 ++++++---
>  arch/arm/mach-vexpress/v2m.c                      |   12 +++++++++---
>  3 files changed, 27 insertions(+), 9 deletions(-)
> 
> diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
> index c65cc3b..11cb248 100644
> --- a/arch/arm/mach-vexpress/ct-ca9x4.c
> +++ b/arch/arm/mach-vexpress/ct-ca9x4.c
> @@ -66,8 +66,15 @@ static void __init ct_ca9x4_init_irq(void)
>  
>  static void ct_ca9x4_clcd_enable(struct clcd_fb *fb)
>  {
> -	v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0);
> -	v2m_cfg_write(SYS_CFG_DVIMODE | SYS_CFG_SITE_DB1, 2);
> +	u32 site = v2m_get_master_site();
> +
> +	/*
> +	 * Old firmware was using the "site" component of the command
> +	 * to control the DVI muxer (while it should be always 0 ie. MB).
> +	 * Newer firmware uses the data register. Keep both for compatibility.
> +	 */
> +	v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE(site), site);
> +	v2m_cfg_write(SYS_CFG_DVIMODE, 2);
>  }
>  
>  static int ct_ca9x4_clcd_setup(struct clcd_fb *fb)
> @@ -112,7 +119,9 @@ static long ct_round(struct clk *clk, unsigned long rate)
>  
>  static int ct_set(struct clk *clk, unsigned long rate)
>  {
> -	return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_DB1 | 1, rate);
> +	u32 site = v2m_get_master_site();
> +
> +	return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(site) | 1, rate);
>  }
>  
>  static const struct clk_ops osc1_clk_ops = {
> diff --git a/arch/arm/mach-vexpress/include/mach/motherboard.h b/arch/arm/mach-vexpress/include/mach/motherboard.h
> index 31a9289..f004ec9 100644
> --- a/arch/arm/mach-vexpress/include/mach/motherboard.h
> +++ b/arch/arm/mach-vexpress/include/mach/motherboard.h
> @@ -104,9 +104,10 @@
>  #define SYS_CFG_REBOOT		(9 << 20)
>  #define SYS_CFG_DVIMODE		(11 << 20)
>  #define SYS_CFG_POWER		(12 << 20)
> -#define SYS_CFG_SITE_MB		(0 << 16)
> -#define SYS_CFG_SITE_DB1	(1 << 16)
> -#define SYS_CFG_SITE_DB2	(2 << 16)
> +#define SYS_CFG_SITE(n)		((n) << 16)
> +#define SYS_CFG_SITE_MB		0

There are three uses of this latter macro you have left unaltered: in
v2m_osc1_set(), v2m_power_off() and v2m_restart(). Now 0 == (0<<16) so
the code will be functionally identical, but they should really be
updated replace SYS_CFG_SITE_MB with SYS_CFG_SITE(SYS_CFG_SITE_MB).
Though that looks a bit messy, perhaps instead we could have something
like...

#define SITE_MB	 0
#define SITE_DB1 1
#define SITE_DB2 2
#define SYS_CFG_SITE(n)		((n) << 16)
#define SYS_CFG_SITE_MB		SYS_CFG_SITE(SITE_MB)
#define SYS_CFG_SITE_DB1	SYS_CFG_SITE(SITE_DB1)
#define SYS_CFG_SITE_DB2	SYS_CFG_SITE(SITE_DB2)

> +#define SYS_CFG_SITE_DB1	1
> +#define SYS_CFG_SITE_DB2	2
>  #define SYS_CFG_STACK(n)	((n) << 12)
>  
>  #define SYS_CFG_ERR		(1 << 1)
> @@ -122,6 +123,8 @@ void v2m_flags_set(u32 data);
>  #define SYS_MISC_MASTERSITE	(1 << 14)
>  #define SYS_PROCIDx_HBI_MASK	0xfff
>  
> +int v2m_get_master_site(void);
> +
>  /*
>   * Core tile IDs
>   */
> diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
> index fde26ad..aa6f9a6 100644
> --- a/arch/arm/mach-vexpress/v2m.c
> +++ b/arch/arm/mach-vexpress/v2m.c
> @@ -147,6 +147,13 @@ void __init v2m_flags_set(u32 data)
>  	writel(data, v2m_sysreg_base + V2M_SYS_FLAGSSET);
>  }
>  
> +int __init v2m_get_master_site(void)
> +{
> +	u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC);
> +
> +	return misc & SYS_MISC_MASTERSITE ? SYS_CFG_SITE_DB2 : SYS_CFG_SITE_DB1;
> +}
> +
>  
>  static struct resource v2m_pcie_i2c_resource = {
>  	.start	= V2M_SERIAL_BUS_PCI,
> @@ -413,7 +420,6 @@ static void v2m_restart(char str, const char *cmd)
>  	if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE_MB, 0))
>  		printk(KERN_EMERG "Unable to reboot\n");
>  }
> -

There's a spurious blank line deletion above.

>  struct ct_desc *ct_desc;
>  
>  static struct ct_desc *ct_descs[] __initdata = {
> @@ -605,8 +611,8 @@ void __init v2m_dt_init_early(void)
>  
>  	/* Confirm board type against DT property, if available */
>  	if (of_property_read_u32(allnodes, "arm,hbi", &dt_hbi) == 0) {
> -		u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC);
> -		u32 id = readl(v2m_sysreg_base + (misc & SYS_MISC_MASTERSITE ?
> +		int site = v2m_get_master_site();
> +		u32 id = readl(v2m_sysreg_base + (site == SYS_CFG_SITE_DB2 ?
>  				V2M_SYS_PROCID1 : V2M_SYS_PROCID0));
>  		u32 hbi = id & SYS_PROCIDx_HBI_MASK;
>  

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/2] ARM: vexpress: Check master site in daughterboard's sysctl operations
  2012-06-12  8:58 ` [PATCH 1/2] ARM: vexpress: Check master site in daughterboard's sysctl operations Jon Medhurst (Tixy)
@ 2012-06-12  9:08   ` Pawel Moll
  2012-06-12 13:02   ` Jon Medhurst (Tixy)
  1 sibling, 0 replies; 6+ messages in thread
From: Pawel Moll @ 2012-06-12  9:08 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2012-06-12 at 09:58 +0100, Jon Medhurst (Tixy) wrote:
> On Fri, 2012-06-08 at 13:50 +0100, Pawel Moll wrote:
> > With recent enough motherboard firmware, core tile can be fitted
> > in either of the two daughterboard sites. The non-DT tile code for
> > V2P-CA9 did not check that when configuring DVI output nor setting
> > CLCD pixel clock.
> > 
> > Fixed now, providing "get master site" API in motherboard's code.
> > 
> > Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> 
> This patch makes an Ubuntu boot always hang for me, about the time it
> would switch to GUI mode, it's not very consistent unfortunately.
> 
> If I modify ct_ca9x4_clcd_enable() to replace "v2m_get_master_site()"
> with "1" then boot is OK. Even though if I put code it to test the
> return value from v2m_get_master_site() it shows it gives 1.
> 
> I am running stock Version 3 firmware on my vexpress.

Thanks for testing, I'll try to reproduce your problem here.

> > diff --git a/arch/arm/mach-vexpress/include/mach/motherboard.h b/arch/arm/mach-vexpress/include/mach/motherboard.h
> > index 31a9289..f004ec9 100644
> > --- a/arch/arm/mach-vexpress/include/mach/motherboard.h
> > +++ b/arch/arm/mach-vexpress/include/mach/motherboard.h
> > @@ -104,9 +104,10 @@
> >  #define SYS_CFG_REBOOT		(9 << 20)
> >  #define SYS_CFG_DVIMODE		(11 << 20)
> >  #define SYS_CFG_POWER		(12 << 20)
> > -#define SYS_CFG_SITE_MB		(0 << 16)
> > -#define SYS_CFG_SITE_DB1	(1 << 16)
> > -#define SYS_CFG_SITE_DB2	(2 << 16)
> > +#define SYS_CFG_SITE(n)		((n) << 16)
> > +#define SYS_CFG_SITE_MB		0
> 
> There are three uses of this latter macro you have left unaltered: in
> v2m_osc1_set(), v2m_power_off() and v2m_restart(). 

Good point. I did grep for _DBx, forgot to do the same for _MB.

Having said that - I have to rework this whole lot anyway, to get all
functionality we need from sysreg/ctl, so don't bother with carrying
this patch in your tree.

Cheers!

Pawe?

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 1/2] ARM: vexpress: Check master site in daughterboard's sysctl operations
  2012-06-12  8:58 ` [PATCH 1/2] ARM: vexpress: Check master site in daughterboard's sysctl operations Jon Medhurst (Tixy)
  2012-06-12  9:08   ` Pawel Moll
@ 2012-06-12 13:02   ` Jon Medhurst (Tixy)
  1 sibling, 0 replies; 6+ messages in thread
From: Jon Medhurst (Tixy) @ 2012-06-12 13:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, 2012-06-12 at 09:58 +0100, Jon Medhurst (Tixy) wrote:
> On Fri, 2012-06-08 at 13:50 +0100, Pawel Moll wrote:
> > With recent enough motherboard firmware, core tile can be fitted
> > in either of the two daughterboard sites. The non-DT tile code for
> > V2P-CA9 did not check that when configuring DVI output nor setting
> > CLCD pixel clock.
> > 
> > Fixed now, providing "get master site" API in motherboard's code.
> > 
> > Signed-off-by: Pawel Moll <pawel.moll@arm.com>
> 
> This patch makes an Ubuntu boot always hang for me, about the time it
> would switch to GUI mode, it's not very consistent unfortunately.

I've found the cause of the problem, v2m_get_master_site() is marked
__init but is used by the non __init function ct_ca9x4_clcd_enable(). So
when Ubuntu GUI startup messes with the display it ends up calling into
freed memory.

Dropping __init from ct_ca9x4_clcd_enable() fixes my boot failures.

-- 
Tixy

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH 2/2] ARM: vexpress: Initial common clock support
  2012-06-08 12:50 ` [PATCH 2/2] ARM: vexpress: Initial common clock support Pawel Moll
@ 2012-06-13 10:07   ` Jon Medhurst (Tixy)
  0 siblings, 0 replies; 6+ messages in thread
From: Jon Medhurst (Tixy) @ 2012-06-13 10:07 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, 2012-06-08 at 13:50 +0100, Pawel Moll wrote:
> This patch makes Versatile Express use the common clock framework
> instead of the plat-versatile implementation (which remains intact
> for mach-versatile and mach-realview sake).
> 
> It defines clock provider for VE's OSCs (clock generators) and
> registers all required fixed and variable clock sources (for both
> motherboard and core tile).
> 
> Signed-off-by: Pawel Moll <pawel.moll@arm.com>

Tested-by: Jon Medhurst <tixy@linaro.org>

(Tested on CA9 non-device tree and CA15-TC1 with device tree.)

> ---
>  arch/arm/Kconfig                                  |    2 +-
>  arch/arm/mach-vexpress/ct-ca9x4.c                 |   55 +----
>  arch/arm/mach-vexpress/include/mach/clkdev.h      |   15 --
>  arch/arm/mach-vexpress/include/mach/motherboard.h |   20 ++
>  arch/arm/mach-vexpress/v2m.c                      |  253 +++++++++------------
>  arch/arm/plat-versatile/Kconfig                   |    5 +
>  arch/arm/plat-versatile/Makefile                  |    2 +-
>  7 files changed, 150 insertions(+), 202 deletions(-)
>  delete mode 100644 arch/arm/mach-vexpress/include/mach/clkdev.h
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index 84449dd..6f3370e 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -306,7 +306,7 @@ config ARCH_VEXPRESS
>  	select ARM_AMBA
>  	select ARM_TIMER_SP804
>  	select CLKDEV_LOOKUP
> -	select HAVE_MACH_CLKDEV
> +	select COMMON_CLK
>  	select GENERIC_CLOCKEVENTS
>  	select HAVE_CLK
>  	select HAVE_PATA_PLATFORM
> diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
> index 11cb248..3ef3fda 100644
> --- a/arch/arm/mach-vexpress/ct-ca9x4.c
> +++ b/arch/arm/mach-vexpress/ct-ca9x4.c
> @@ -111,48 +111,22 @@ static struct amba_device *ct_ca9x4_amba_devs[] __initdata = {
>  	&gpio_device,
>  };
>  
> +static struct v2m_osc ct_osc1 = {
> +	.osc = 1,
> +	.rate_min = 10000000,
> +	.rate_max = 80000000,
> +	.rate_default = 23750000,
> +};
>  
> -static long ct_round(struct clk *clk, unsigned long rate)
> -{
> -	return rate;
> -}
> -
> -static int ct_set(struct clk *clk, unsigned long rate)
> +static void __init ct_ca9x4_init_clk(void)
>  {
> -	u32 site = v2m_get_master_site();
> +	struct clk *clk;
>  
> -	return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(site) | 1, rate);
> +	ct_osc1.site = v2m_get_master_site();
> +	clk = v2m_osc_register("ct:osc1", &ct_osc1);
> +	clk_register_clkdev(clk, NULL, "ct:clcd");
>  }
>  
> -static const struct clk_ops osc1_clk_ops = {
> -	.round	= ct_round,
> -	.set	= ct_set,
> -};
> -
> -static struct clk osc1_clk = {
> -	.ops	= &osc1_clk_ops,
> -	.rate	= 24000000,
> -};
> -
> -static struct clk ct_sp804_clk = {
> -	.rate	= 1000000,
> -};
> -
> -static struct clk_lookup lookups[] = {
> -	{	/* CLCD */
> -		.dev_id		= "ct:clcd",
> -		.clk		= &osc1_clk,
> -	}, {	/* SP804 timers */
> -		.dev_id		= "sp804",
> -		.con_id		= "ct-timer0",
> -		.clk		= &ct_sp804_clk,
> -	}, {	/* SP804 timers */
> -		.dev_id		= "sp804",
> -		.con_id		= "ct-timer1",
> -		.clk		= &ct_sp804_clk,
> -	},
> -};
> -
>  static struct resource pmu_resources[] = {
>  	[0] = {
>  		.start	= IRQ_CT_CA9X4_PMU_CPU0,
> @@ -183,11 +157,6 @@ static struct platform_device pmu_device = {
>  	.resource	= pmu_resources,
>  };
>  
> -static void __init ct_ca9x4_init_early(void)
> -{
> -	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
> -}
> -
>  static void __init ct_ca9x4_init(void)
>  {
>  	int i;
> @@ -243,8 +212,8 @@ struct ct_desc ct_ca9x4_desc __initdata = {
>  	.id		= V2M_CT_ID_CA9,
>  	.name		= "CA9x4",
>  	.map_io		= ct_ca9x4_map_io,
> -	.init_early	= ct_ca9x4_init_early,
>  	.init_irq	= ct_ca9x4_init_irq,
> +	.init_clk	= ct_ca9x4_init_clk,
>  	.init_tile	= ct_ca9x4_init,
>  #ifdef CONFIG_SMP
>  	.init_cpu_map	= ct_ca9x4_init_cpu_map,
> diff --git a/arch/arm/mach-vexpress/include/mach/clkdev.h b/arch/arm/mach-vexpress/include/mach/clkdev.h
> deleted file mode 100644
> index 3f8307d..0000000
> --- a/arch/arm/mach-vexpress/include/mach/clkdev.h
> +++ /dev/null
> @@ -1,15 +0,0 @@
> -#ifndef __ASM_MACH_CLKDEV_H
> -#define __ASM_MACH_CLKDEV_H
> -
> -#include <plat/clock.h>
> -
> -struct clk {
> -	const struct clk_ops	*ops;
> -	unsigned long		rate;
> -	const struct icst_params *params;
> -};
> -
> -#define __clk_get(clk) ({ 1; })
> -#define __clk_put(clk) do { } while (0)
> -
> -#endif
> diff --git a/arch/arm/mach-vexpress/include/mach/motherboard.h b/arch/arm/mach-vexpress/include/mach/motherboard.h
> index f004ec9..2762263 100644
> --- a/arch/arm/mach-vexpress/include/mach/motherboard.h
> +++ b/arch/arm/mach-vexpress/include/mach/motherboard.h
> @@ -1,6 +1,8 @@
>  #ifndef __MACH_MOTHERBOARD_H
>  #define __MACH_MOTHERBOARD_H
>  
> +#include <linux/clk-provider.h>
> +
>  /*
>   * Physical addresses, offset from V2M_PA_CS0-3
>   */
> @@ -138,6 +140,7 @@ struct ct_desc {
>  	void			(*map_io)(void);
>  	void			(*init_early)(void);
>  	void			(*init_irq)(void);
> +	void			(*init_clk)(void);
>  	void			(*init_tile)(void);
>  #ifdef CONFIG_SMP
>  	void			(*init_cpu_map)(void);
> @@ -147,4 +150,21 @@ struct ct_desc {
>  
>  extern struct ct_desc *ct_desc;
>  
> +/*
> + * OSC clock provider
> + */
> +struct v2m_osc {
> +	struct clk_hw hw;
> +	u8 site; /* 0 = motherboard, 1 = site 1, 2 = site 2 */
> +	u8 stack; /* board stack position */
> +	u16 osc;
> +	unsigned long rate_min;
> +	unsigned long rate_max;
> +	unsigned long rate_default;
> +};
> +
> +#define to_v2m_osc(osc) container_of(osc, struct v2m_osc, hw)
> +
> +struct clk *v2m_osc_register(const char *name, struct v2m_osc *osc);
> +
>  #endif
> diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
> index aa6f9a6..e1e2415 100644
> --- a/arch/arm/mach-vexpress/v2m.c
> +++ b/arch/arm/mach-vexpress/v2m.c
> @@ -16,6 +16,7 @@
>  #include <linux/spinlock.h>
>  #include <linux/usb/isp1760.h>
>  #include <linux/clkdev.h>
> +#include <linux/clk-provider.h>
>  #include <linux/mtd/physmap.h>
>  
>  #include <asm/arch_timer.h>
> @@ -81,16 +82,6 @@ static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
>  	sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0");
>  }
>  
> -static void __init v2m_timer_init(void)
> -{
> -	v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K));
> -	v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
> -}
> -
> -static struct sys_timer v2m_timer = {
> -	.init	= v2m_timer_init,
> -};
> -
>  
>  static DEFINE_SPINLOCK(v2m_cfg_lock);
>  
> @@ -326,86 +317,135 @@ static struct amba_device *v2m_amba_devs[] __initdata = {
>  };
>  
> 
> -static long v2m_osc_round(struct clk *clk, unsigned long rate)
> +static unsigned long v2m_osc_recalc_rate(struct clk_hw *hw,
> +		unsigned long parent_rate)
> +{
> +	struct v2m_osc *osc = to_v2m_osc(hw);
> +
> +	return !parent_rate ? osc->rate_default : parent_rate;
> +}
> +
> +static long v2m_osc_round_rate(struct clk_hw *hw, unsigned long rate,
> +		unsigned long *parent_rate)
>  {
> +	struct v2m_osc *osc = to_v2m_osc(hw);
> +
> +	if (WARN_ON(rate < osc->rate_min))
> +		rate = osc->rate_min;
> +
> +	if (WARN_ON(rate > osc->rate_max))
> +		rate = osc->rate_max;
> +
>  	return rate;
>  }
>  
> -static int v2m_osc1_set(struct clk *clk, unsigned long rate)
> +static int v2m_osc_set_rate(struct clk_hw *hw, unsigned long rate,
> +		unsigned long parent_rate)
>  {
> -	return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_MB | 1, rate);
> +	struct v2m_osc *osc = to_v2m_osc(hw);
> +
> +	v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(osc->site) |
> +		SYS_CFG_STACK(osc->stack) | osc->osc, rate);
> +
> +	return 0;
>  }
>  
> -static const struct clk_ops osc1_clk_ops = {
> -	.round	= v2m_osc_round,
> -	.set	= v2m_osc1_set,
> +static struct clk_ops v2m_osc_ops = {
> +	.recalc_rate = v2m_osc_recalc_rate,
> +	.round_rate = v2m_osc_round_rate,
> +	.set_rate = v2m_osc_set_rate,
>  };
>  
> -static struct clk osc1_clk = {
> -	.ops	= &osc1_clk_ops,
> -	.rate	= 24000000,
> +struct clk * __init v2m_osc_register(const char *name, struct v2m_osc *osc)
> +{
> +	struct clk_init_data init;
> +
> +	WARN_ON(osc->site > 2);
> +	WARN_ON(osc->stack > 15);
> +	WARN_ON(osc->osc > 4095);
> +
> +	init.name = name;
> +	init.ops = &v2m_osc_ops;
> +	init.flags = CLK_IS_ROOT;
> +	init.num_parents = 0;
> +
> +	osc->hw.init = &init;
> +
> +	return clk_register(NULL, &osc->hw);
> +}
> +
> +static struct v2m_osc v2m_mb_osc1 = {
> +	.site = SYS_CFG_SITE_MB,
> +	.osc = 1,
> +	.rate_min = 23750000,
> +	.rate_max = 63500000,
> +	.rate_default = 23750000,
>  };
>  
> -static struct clk osc2_clk = {
> -	.rate	= 24000000,
> +static const char *v2m_ref_clk_periphs[] __initconst = {
> +	"mb:wdt",	"1000f000.wdt",	"1c0f0000.wdt",	/* SP805 WDT */
>  };
>  
> -static struct clk v2m_sp804_clk = {
> -	.rate	= 1000000,
> +static const char *v2m_osc1_periphs[] __initconst = {
> +	"mb:clcd",	"1001f000.clcd", "1c1f0000.clcd",	/* PL111 CLCD */
>  };
>  
> -static struct clk v2m_ref_clk = {
> -	.rate   = 32768,
> +static const char *v2m_osc2_periphs[] __initconst = {
> +	"mb:mmci",	"10005000.mmci", "1c050000.mmci",	/* PL180 MMCI */
> +	"mb:kmi0",	"10006000.kmi",	"1c060000.kmi",	/* PL050 KMI0 */
> +	"mb:kmi1",	"10007000.kmi",	"1c070000.kmi",	/* PL050 KMI1 */
> +	"mb:uart0", "10009000.uart", "1c090000.uart",	/* PL011 UART0 */
> +	"mb:uart1", "1000a000.uart", "1c0a0000.uart",	/* PL011 UART1 */
> +	"mb:uart2", "1000b000.uart", "1c0b0000.uart",	/* PL011 UART2 */
> +	"mb:uart3", "1000c000.uart", "1c0c0000.uart",	/* PL011 UART3 */
>  };
>  
> -static struct clk dummy_apb_pclk;
> -
> -static struct clk_lookup v2m_lookups[] = {
> -	{	/* AMBA bus clock */
> -		.con_id		= "apb_pclk",
> -		.clk		= &dummy_apb_pclk,
> -	}, {	/* UART0 */
> -		.dev_id		= "mb:uart0",
> -		.clk		= &osc2_clk,
> -	}, {	/* UART1 */
> -		.dev_id		= "mb:uart1",
> -		.clk		= &osc2_clk,
> -	}, {	/* UART2 */
> -		.dev_id		= "mb:uart2",
> -		.clk		= &osc2_clk,
> -	}, {	/* UART3 */
> -		.dev_id		= "mb:uart3",
> -		.clk		= &osc2_clk,
> -	}, {	/* KMI0 */
> -		.dev_id		= "mb:kmi0",
> -		.clk		= &osc2_clk,
> -	}, {	/* KMI1 */
> -		.dev_id		= "mb:kmi1",
> -		.clk		= &osc2_clk,
> -	}, {	/* MMC0 */
> -		.dev_id		= "mb:mmci",
> -		.clk		= &osc2_clk,
> -	}, {	/* CLCD */
> -		.dev_id		= "mb:clcd",
> -		.clk		= &osc1_clk,
> -	}, {	/* SP805 WDT */
> -		.dev_id		= "mb:wdt",
> -		.clk		= &v2m_ref_clk,
> -	}, {	/* SP804 timers */
> -		.dev_id		= "sp804",
> -		.con_id		= "v2m-timer0",
> -		.clk		= &v2m_sp804_clk,
> -	}, {	/* SP804 timers */
> -		.dev_id		= "sp804",
> -		.con_id		= "v2m-timer1",
> -		.clk		= &v2m_sp804_clk,
> -	},
> +static void __init v2m_clk_init(void)
> +{
> +	struct clk *clk;
> +	int i;
> +
> +	clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL,
> +			CLK_IS_ROOT, 0);
> +	WARN_ON(clk_register_clkdev(clk, "abp_pclk", NULL));
> +
> +	clk = clk_register_fixed_rate(NULL, "mb:ref_clk", NULL,
> +			CLK_IS_ROOT, 32768);
> +	for (i = 0; i < ARRAY_SIZE(v2m_ref_clk_periphs); i++)
> +		WARN_ON(clk_register_clkdev(clk, NULL, v2m_ref_clk_periphs[i]));
> +
> +	clk = clk_register_fixed_rate(NULL, "mb:sp804_clk", NULL,
> +			CLK_IS_ROOT, 1000000);
> +	WARN_ON(clk_register_clkdev(clk, "v2m-timer0", "sp804"));
> +	WARN_ON(clk_register_clkdev(clk, "v2m-timer1", "sp804"));
> +
> +	clk = v2m_osc_register("mb:osc1", &v2m_mb_osc1);
> +	for (i = 0; i < ARRAY_SIZE(v2m_osc1_periphs); i++)
> +		WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc1_periphs[i]));
> +
> +	clk = clk_register_fixed_rate(NULL, "mb:osc2", NULL,
> +			CLK_IS_ROOT, 24000000);
> +	for (i = 0; i < ARRAY_SIZE(v2m_osc2_periphs); i++)
> +		WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc2_periphs[i]));
> +}
> +
> +static void __init v2m_timer_init(void)
> +{
> +	v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K));
> +	v2m_clk_init();
> +	if (ct_desc->init_clk)
> +		ct_desc->init_clk();
> +	v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
> +}
> +
> +static struct sys_timer v2m_timer = {
> +	.init	= v2m_timer_init,
>  };
>  
>  static void __init v2m_init_early(void)
>  {
> -	ct_desc->init_early();
> -	clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups));
> +	if (ct_desc->init_early)
> +		ct_desc->init_early();
>  	versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
>  }
>  
> @@ -528,77 +568,6 @@ void __init v2m_dt_map_io(void)
>  #endif
>  }
>  
> -static struct clk_lookup v2m_dt_lookups[] = {
> -	{	/* AMBA bus clock */
> -		.con_id		= "apb_pclk",
> -		.clk		= &dummy_apb_pclk,
> -	}, {	/* SP804 timers */
> -		.dev_id		= "sp804",
> -		.con_id		= "v2m-timer0",
> -		.clk		= &v2m_sp804_clk,
> -	}, {	/* SP804 timers */
> -		.dev_id		= "sp804",
> -		.con_id		= "v2m-timer1",
> -		.clk		= &v2m_sp804_clk,
> -	}, {	/* PL180 MMCI */
> -		.dev_id		= "mb:mmci", /* 10005000.mmci */
> -		.clk		= &osc2_clk,
> -	}, {	/* PL050 KMI0 */
> -		.dev_id		= "10006000.kmi",
> -		.clk		= &osc2_clk,
> -	}, {	/* PL050 KMI1 */
> -		.dev_id		= "10007000.kmi",
> -		.clk		= &osc2_clk,
> -	}, {	/* PL011 UART0 */
> -		.dev_id		= "10009000.uart",
> -		.clk		= &osc2_clk,
> -	}, {	/* PL011 UART1 */
> -		.dev_id		= "1000a000.uart",
> -		.clk		= &osc2_clk,
> -	}, {	/* PL011 UART2 */
> -		.dev_id		= "1000b000.uart",
> -		.clk		= &osc2_clk,
> -	}, {	/* PL011 UART3 */
> -		.dev_id		= "1000c000.uart",
> -		.clk		= &osc2_clk,
> -	}, {	/* SP805 WDT */
> -		.dev_id		= "1000f000.wdt",
> -		.clk		= &v2m_ref_clk,
> -	}, {	/* PL111 CLCD */
> -		.dev_id		= "1001f000.clcd",
> -		.clk		= &osc1_clk,
> -	},
> -	/* RS1 memory map */
> -	{	/* PL180 MMCI */
> -		.dev_id		= "mb:mmci", /* 1c050000.mmci */
> -		.clk		= &osc2_clk,
> -	}, {	/* PL050 KMI0 */
> -		.dev_id		= "1c060000.kmi",
> -		.clk		= &osc2_clk,
> -	}, {	/* PL050 KMI1 */
> -		.dev_id		= "1c070000.kmi",
> -		.clk		= &osc2_clk,
> -	}, {	/* PL011 UART0 */
> -		.dev_id		= "1c090000.uart",
> -		.clk		= &osc2_clk,
> -	}, {	/* PL011 UART1 */
> -		.dev_id		= "1c0a0000.uart",
> -		.clk		= &osc2_clk,
> -	}, {	/* PL011 UART2 */
> -		.dev_id		= "1c0b0000.uart",
> -		.clk		= &osc2_clk,
> -	}, {	/* PL011 UART3 */
> -		.dev_id		= "1c0c0000.uart",
> -		.clk		= &osc2_clk,
> -	}, {	/* SP805 WDT */
> -		.dev_id		= "1c0f0000.wdt",
> -		.clk		= &v2m_ref_clk,
> -	}, {	/* PL111 CLCD */
> -		.dev_id		= "1c1f0000.clcd",
> -		.clk		= &osc1_clk,
> -	},
> -};
> -
>  void __init v2m_dt_init_early(void)
>  {
>  	struct device_node *node;
> @@ -620,8 +589,6 @@ void __init v2m_dt_init_early(void)
>  			pr_warning("vexpress: DT HBI (%x) is not matching "
>  					"hardware (%x)!\n", dt_hbi, hbi);
>  	}
> -
> -	clkdev_add_table(v2m_dt_lookups, ARRAY_SIZE(v2m_dt_lookups));
>  }
>  
>  static  struct of_device_id vexpress_irq_match[] __initdata = {
> @@ -643,6 +610,8 @@ static void __init v2m_dt_timer_init(void)
>  	node = of_find_compatible_node(NULL, NULL, "arm,sp810");
>  	v2m_sysctl_init(of_iomap(node, 0));
>  
> +	v2m_clk_init();
> +
>  	err = of_property_read_string(of_aliases, "arm,v2m_timer", &path);
>  	if (WARN_ON(err))
>  		return;
> diff --git a/arch/arm/plat-versatile/Kconfig b/arch/arm/plat-versatile/Kconfig
> index 81ee7cc..4b9f4bf 100644
> --- a/arch/arm/plat-versatile/Kconfig
> +++ b/arch/arm/plat-versatile/Kconfig
> @@ -1,5 +1,10 @@
>  if PLAT_VERSATILE
>  
> +config PLAT_VERSATILE_CLOCK
> +	bool
> +	default y
> +	depends on !COMMON_CLK
> +
>  config PLAT_VERSATILE_CLCD
>  	bool
>  
> diff --git a/arch/arm/plat-versatile/Makefile b/arch/arm/plat-versatile/Makefile
> index a5cb194..272769a8 100644
> --- a/arch/arm/plat-versatile/Makefile
> +++ b/arch/arm/plat-versatile/Makefile
> @@ -1,4 +1,4 @@
> -obj-y	:= clock.o
> +obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o
>  obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
>  obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o
>  obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2012-06-13 10:07 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-06-08 12:50 [PATCH 1/2] ARM: vexpress: Check master site in daughterboard's sysctl operations Pawel Moll
2012-06-08 12:50 ` [PATCH 2/2] ARM: vexpress: Initial common clock support Pawel Moll
2012-06-13 10:07   ` Jon Medhurst (Tixy)
2012-06-12  8:58 ` [PATCH 1/2] ARM: vexpress: Check master site in daughterboard's sysctl operations Jon Medhurst (Tixy)
2012-06-12  9:08   ` Pawel Moll
2012-06-12 13:02   ` Jon Medhurst (Tixy)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).