From 6f69c7f21ce89409ccc54bd596434fa61d5b26ff Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Tue, 25 Jun 2013 22:05:24 +0200 Subject: ARM: zynq: Move clock_init from slcr to common Preparation step for next changes. Signed-off-by: Steffen Trumtrar Signed-off-by: Michal Simek --- arch/arm/mach-zynq/common.c | 2 ++ arch/arm/mach-zynq/slcr.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-zynq') diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 1db2a5ca..bf6717f 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -64,6 +64,8 @@ static void __init zynq_init_machine(void) static void __init zynq_timer_init(void) { zynq_slcr_init(); + + zynq_clock_init(zynq_slcr_base); clocksource_of_init(); } diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index 1836d5a..59ad09f 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -106,8 +106,6 @@ int __init zynq_slcr_init(void) pr_info("%s mapped to %p\n", np->name, zynq_slcr_base); - zynq_clock_init(zynq_slcr_base); - of_node_put(np); return 0; -- cgit v1.1 From 016f4dcae81e842a2b7dbfbc0fc9257f9f16e785 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 26 Nov 2013 15:41:31 +0100 Subject: ARM: zynq: Split slcr in two parts Split the slcr into an early part for unlocking and cpu starting and a later syscon driver. Also add "syscon" compatible property for slcr. Signed-off-by: Steffen Trumtrar Signed-off-by: Michal Simek --- arch/arm/mach-zynq/Kconfig | 1 + arch/arm/mach-zynq/common.c | 4 +++- arch/arm/mach-zynq/common.h | 1 + arch/arm/mach-zynq/slcr.c | 26 ++++++++++++++++++++++++-- 4 files changed, 29 insertions(+), 3 deletions(-) (limited to 'arch/arm/mach-zynq') diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig index 6b04260..323e505 100644 --- a/arch/arm/mach-zynq/Kconfig +++ b/arch/arm/mach-zynq/Kconfig @@ -14,5 +14,6 @@ config ARCH_ZYNQ select SPARSE_IRQ select CADENCE_TTC_TIMER select ARM_GLOBAL_TIMER + select MFD_SYSCON help Support for Xilinx Zynq ARM Cortex A9 Platform diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index bf6717f..38401cf 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -59,11 +59,13 @@ static void __init zynq_init_machine(void) of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); platform_device_register(&zynq_cpuidle_device); + + zynq_slcr_init(); } static void __init zynq_timer_init(void) { - zynq_slcr_init(); + zynq_early_slcr_init(); zynq_clock_init(zynq_slcr_base); clocksource_of_init(); diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h index c22c92c..1548b85 100644 --- a/arch/arm/mach-zynq/common.h +++ b/arch/arm/mach-zynq/common.h @@ -20,6 +20,7 @@ void zynq_secondary_startup(void); extern int zynq_slcr_init(void); +extern int zynq_early_slcr_init(void); extern void zynq_slcr_system_reset(void); extern void zynq_slcr_cpu_stop(int cpu); extern void zynq_slcr_cpu_start(int cpu); diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index 59ad09f..899f979 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -15,7 +15,9 @@ */ #include +#include #include +#include #include #include "common.h" @@ -30,6 +32,7 @@ #define SLCR_A9_CPU_RST 0x1 void __iomem *zynq_slcr_base; +static struct regmap *zynq_slcr_regmap; /** * zynq_slcr_system_reset - Reset the entire system. @@ -80,13 +83,32 @@ void zynq_slcr_cpu_stop(int cpu) } /** - * zynq_slcr_init - * Returns 0 on success, negative errno otherwise. + * zynq_slcr_init - Regular slcr driver init + * + * Return: 0 on success, negative errno otherwise. * * Called early during boot from platform code to remap SLCR area. */ int __init zynq_slcr_init(void) { + zynq_slcr_regmap = syscon_regmap_lookup_by_compatible("xlnx,zynq-slcr"); + if (IS_ERR(zynq_slcr_regmap)) { + pr_err("%s: failed to find zynq-slcr\n", __func__); + return -ENODEV; + } + + return 0; +} + +/** + * zynq_early_slcr_init - Early slcr init function + * + * Return: 0 on success, negative errno otherwise. + * + * Called very early during boot from platform code to unlock SLCR. + */ +int __init zynq_early_slcr_init(void) +{ struct device_node *np; np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-slcr"); -- cgit v1.1 From 5e2182803497c22d50675f0f3af12bf5305e8716 Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Tue, 26 Nov 2013 14:02:44 +0100 Subject: ARM: zynq: Hang iomapped slcr address on device_node For later usage by zynq clk driver. Signed-off-by: Steffen Trumtrar Signed-off-by: Michal Simek --- arch/arm/mach-zynq/slcr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/arm/mach-zynq') diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index 899f979..db5cb31 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -123,6 +123,8 @@ int __init zynq_early_slcr_init(void) BUG(); } + np->data = (__force void *)zynq_slcr_base; + /* unlock the SLCR so that registers can be changed */ writel(SLCR_UNLOCK_MAGIC, zynq_slcr_base + SLCR_UNLOCK_OFFSET); -- cgit v1.1 From b0504e39c27b00101c9c1fa2c58fd896ae0f64f5 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 18 Nov 2013 16:48:19 +0100 Subject: ARM: zynq: Map I/O memory on clkc init The clkc has its registers in the range of the slcr. Instead of passing around the slcr base address pointer, let the clkc get the address from the DT. This prepares the slcr to be a real driver with multiple memory ranges (slcr, clocks, pinctrl,...) Signed-off-by: Steffen Trumtrar Signed-off-by: Michal Simek --- arch/arm/mach-zynq/common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/mach-zynq') diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 38401cf..93ea19b 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -67,7 +67,7 @@ static void __init zynq_timer_init(void) { zynq_early_slcr_init(); - zynq_clock_init(zynq_slcr_base); + zynq_clock_init(); clocksource_of_init(); } -- cgit v1.1 From 7b274efef794fe566ee42f3091276d0598952558 Mon Sep 17 00:00:00 2001 From: Steffen Trumtrar Date: Sat, 29 Jun 2013 09:20:17 +0200 Subject: ARM: zynq: Make zynq_slcr_base static The pointer doesn't need to be passed around any more. Make it static. Signed-off-by: Steffen Trumtrar Signed-off-by: Michal Simek --- arch/arm/mach-zynq/common.h | 1 - arch/arm/mach-zynq/slcr.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/arm/mach-zynq') diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h index 1548b85..b097844 100644 --- a/arch/arm/mach-zynq/common.h +++ b/arch/arm/mach-zynq/common.h @@ -34,7 +34,6 @@ extern int zynq_cpun_start(u32 address, int cpu); extern struct smp_operations zynq_smp_ops __initdata; #endif -extern void __iomem *zynq_slcr_base; extern void __iomem *zynq_scu_base; /* Hotplug */ diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index db5cb31..34c1c2a 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -31,7 +31,7 @@ #define SLCR_A9_CPU_CLKSTOP 0x10 #define SLCR_A9_CPU_RST 0x1 -void __iomem *zynq_slcr_base; +static void __iomem *zynq_slcr_base; static struct regmap *zynq_slcr_regmap; /** -- cgit v1.1 From 871c6971ec38d485fa601f6d9f60cb8d25a5aae1 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Mon, 6 Jan 2014 14:52:02 +0100 Subject: ARM: zynq: Add and use zynq_slcr_read/write() helper functions Use zynq_slcr_read/write helper functions for reg access instead of readl/writel. Also use regmap when it is ready. Signed-off-by: Michal Simek --- arch/arm/mach-zynq/slcr.c | 56 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 8 deletions(-) (limited to 'arch/arm/mach-zynq') diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index 34c1c2a..ab85f4e 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -35,6 +35,42 @@ static void __iomem *zynq_slcr_base; static struct regmap *zynq_slcr_regmap; /** + * zynq_slcr_write - Write to a register in SLCR block + * + * @val: Value to write to the register + * @offset: Register offset in SLCR block + * + * Return: a negative value on error, 0 on success + */ +static int zynq_slcr_write(u32 val, u32 offset) +{ + if (!zynq_slcr_regmap) { + writel(val, zynq_slcr_base + offset); + return 0; + } + + return regmap_write(zynq_slcr_regmap, offset, val); +} + +/** + * zynq_slcr_read - Read a register in SLCR block + * + * @val: Pointer to value to be read from SLCR + * @offset: Register offset in SLCR block + * + * Return: a negative value on error, 0 on success + */ +static int zynq_slcr_read(u32 *val, u32 offset) +{ + if (zynq_slcr_regmap) + return regmap_read(zynq_slcr_regmap, offset, val); + + *val = readl(zynq_slcr_base + offset); + + return 0; +} + +/** * zynq_slcr_system_reset - Reset the entire system. */ void zynq_slcr_system_reset(void) @@ -53,9 +89,9 @@ void zynq_slcr_system_reset(void) * the FSBL not loading the bitstream after soft-reboot * This is a temporary solution until we know more. */ - reboot = readl(zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET); - writel(reboot & 0xF0FFFFFF, zynq_slcr_base + SLCR_REBOOT_STATUS_OFFSET); - writel(1, zynq_slcr_base + SLCR_PS_RST_CTRL_OFFSET); + zynq_slcr_read(&reboot, SLCR_REBOOT_STATUS_OFFSET); + zynq_slcr_write(reboot & 0xF0FFFFFF, SLCR_REBOOT_STATUS_OFFSET); + zynq_slcr_write(1, SLCR_PS_RST_CTRL_OFFSET); } /** @@ -64,11 +100,13 @@ void zynq_slcr_system_reset(void) */ void zynq_slcr_cpu_start(int cpu) { - u32 reg = readl(zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET); + u32 reg; + + zynq_slcr_read(®, SLCR_A9_CPU_RST_CTRL_OFFSET); reg &= ~(SLCR_A9_CPU_RST << cpu); - writel(reg, zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET); + zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET); reg &= ~(SLCR_A9_CPU_CLKSTOP << cpu); - writel(reg, zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET); + zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET); } /** @@ -77,9 +115,11 @@ void zynq_slcr_cpu_start(int cpu) */ void zynq_slcr_cpu_stop(int cpu) { - u32 reg = readl(zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET); + u32 reg; + + zynq_slcr_read(®, SLCR_A9_CPU_RST_CTRL_OFFSET); reg |= (SLCR_A9_CPU_CLKSTOP | SLCR_A9_CPU_RST) << cpu; - writel(reg, zynq_slcr_base + SLCR_A9_CPU_RST_CTRL_OFFSET); + zynq_slcr_write(reg, SLCR_A9_CPU_RST_CTRL_OFFSET); } /** -- cgit v1.1 From 568800731a5b0f6b03d3ee9435b42fecd342454e Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Tue, 26 Nov 2013 14:46:58 +0100 Subject: ARM: zynq: Introduce zynq_slcr_unlock() Call special function for unlocking SLCR. Signed-off-by: Michal Simek --- arch/arm/mach-zynq/slcr.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'arch/arm/mach-zynq') diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index ab85f4e..a37d49a 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -71,6 +71,18 @@ static int zynq_slcr_read(u32 *val, u32 offset) } /** + * zynq_slcr_unlock - Unlock SLCR registers + * + * Return: a negative value on error, 0 on success + */ +static inline int zynq_slcr_unlock(void) +{ + zynq_slcr_write(SLCR_UNLOCK_MAGIC, SLCR_UNLOCK_OFFSET); + + return 0; +} + +/** * zynq_slcr_system_reset - Reset the entire system. */ void zynq_slcr_system_reset(void) @@ -82,7 +94,7 @@ void zynq_slcr_system_reset(void) * Note that this seems to require raw i/o * functions or there's a lockup? */ - writel(SLCR_UNLOCK_MAGIC, zynq_slcr_base + SLCR_UNLOCK_OFFSET); + zynq_slcr_unlock(); /* * Clear 0x0F000000 bits of reboot status register to workaround @@ -166,7 +178,7 @@ int __init zynq_early_slcr_init(void) np->data = (__force void *)zynq_slcr_base; /* unlock the SLCR so that registers can be changed */ - writel(SLCR_UNLOCK_MAGIC, zynq_slcr_base + SLCR_UNLOCK_OFFSET); + zynq_slcr_unlock(); pr_info("%s mapped to %p\n", np->name, zynq_slcr_base); -- cgit v1.1 From 4a32c74e762236a53627536b9b9c1693d3073359 Mon Sep 17 00:00:00 2001 From: Michal Simek Date: Wed, 5 Feb 2014 15:41:51 +0100 Subject: ARM: zynq: Move of_clk_init from clock driver Move of_clk_init() from clock driver to enable options not to use zynq clock driver. Use for example fixed clock setting. Signed-off-by: Michal Simek --- arch/arm/mach-zynq/common.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/arm/mach-zynq') diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c index 93ea19b..5755129 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -68,6 +69,7 @@ static void __init zynq_timer_init(void) zynq_early_slcr_init(); zynq_clock_init(); + of_clk_init(NULL); clocksource_of_init(); } -- cgit v1.1