diff options
author | Olof Johansson <olof@lixom.net> | 2014-05-27 01:52:23 +0400 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2014-05-27 01:52:23 +0400 |
commit | 4fd09120443a47ea1876ecce494205420b94d201 (patch) | |
tree | e8194ee966c0ea64937b8ea3f6ac18652b8e0555 /arch | |
parent | e469d6ba0ac0b75f6cd762fc497d35dec0d11fc2 (diff) | |
parent | eb28d0bb857f01ff972f8b359c962eef9ecf1b64 (diff) | |
download | linux-4fd09120443a47ea1876ecce494205420b94d201.tar.xz |
Merge tag 'zynq-cleanup-for-3.16' of git://git.xilinx.com/linux-xlnx into next/soc
Merge "Xilinx Zynq changes for v3.16" from Michal Simek:
arm: Xilinx Zynq cleanup patches for v3.16
- Add support for BIG Endian
- Add SOC_BUS support
- Sort Kconfig options
- Fix early console
* tag 'zynq-cleanup-for-3.16' of git://git.xilinx.com/linux-xlnx:
ARM: zynq: Enable big-endian
ARM: zynq: Fix uart0 early console virtual address
clocksource: cadence_ttc: Use readl/writel_relaxed instead of __raw
ARM: zynq: Sort Kconfig options
ARM: zynq: Add support for SOC_BUS
Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/boot/dts/zynq-7000.dtsi | 5 | ||||
-rw-r--r-- | arch/arm/include/debug/zynq.S | 10 | ||||
-rw-r--r-- | arch/arm/mach-zynq/Kconfig | 10 | ||||
-rw-r--r-- | arch/arm/mach-zynq/common.c | 71 | ||||
-rw-r--r-- | arch/arm/mach-zynq/common.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-zynq/headsmp.S | 5 | ||||
-rw-r--r-- | arch/arm/mach-zynq/slcr.c | 19 |
7 files changed, 111 insertions, 10 deletions
diff --git a/arch/arm/boot/dts/zynq-7000.dtsi b/arch/arm/boot/dts/zynq-7000.dtsi index c1176abc34d9..80d8e4f3f626 100644 --- a/arch/arm/boot/dts/zynq-7000.dtsi +++ b/arch/arm/boot/dts/zynq-7000.dtsi @@ -177,6 +177,11 @@ }; }; + devcfg: devcfg@f8007000 { + compatible = "xlnx,zynq-devcfg-1.0"; + reg = <0xf8007000 0x100>; + } ; + global_timer: timer@f8f00200 { compatible = "arm,cortex-a9-global-timer"; reg = <0xf8f00200 0x20>; diff --git a/arch/arm/include/debug/zynq.S b/arch/arm/include/debug/zynq.S index 0b762fafa758..bd13dedbdeff 100644 --- a/arch/arm/include/debug/zynq.S +++ b/arch/arm/include/debug/zynq.S @@ -20,18 +20,18 @@ #define UART_SR_TXEMPTY 0x00000008 /* TX FIFO empty */ #define UART0_PHYS 0xE0000000 +#define UART0_VIRT 0xF0000000 #define UART1_PHYS 0xE0001000 -#define UART_SIZE SZ_4K -#define UART_VIRT 0xF0001000 +#define UART1_VIRT 0xF0001000 #if IS_ENABLED(CONFIG_DEBUG_ZYNQ_UART1) # define LL_UART_PADDR UART1_PHYS +# define LL_UART_VADDR UART1_VIRT #else # define LL_UART_PADDR UART0_PHYS +# define LL_UART_VADDR UART0_VIRT #endif -#define LL_UART_VADDR UART_VIRT - .macro addruart, rp, rv, tmp ldr \rp, =LL_UART_PADDR @ physical ldr \rv, =LL_UART_VADDR @ virtual @@ -43,12 +43,14 @@ .macro waituart,rd,rx 1001: ldr \rd, [\rx, #UART_SR_OFFSET] +ARM_BE8( rev \rd, \rd ) tst \rd, #UART_SR_TXEMPTY beq 1001b .endm .macro busyuart,rd,rx 1002: ldr \rd, [\rx, #UART_SR_OFFSET] @ get status register +ARM_BE8( rev \rd, \rd ) tst \rd, #UART_SR_TXFULL @ bne 1002b @ wait if FIFO is full .endm diff --git a/arch/arm/mach-zynq/Kconfig b/arch/arm/mach-zynq/Kconfig index 58c2b844e0a3..573e0db1d0f0 100644 --- a/arch/arm/mach-zynq/Kconfig +++ b/arch/arm/mach-zynq/Kconfig @@ -1,14 +1,16 @@ config ARCH_ZYNQ bool "Xilinx Zynq ARM Cortex A9 Platform" if ARCH_MULTI_V7 - select ARM_AMBA - select ARM_GIC select ARCH_HAS_CPUFREQ select ARCH_HAS_OPP + select ARCH_SUPPORTS_BIG_ENDIAN + select ARM_AMBA + select ARM_GIC + select ARM_GLOBAL_TIMER if !CPU_FREQ + select CADENCE_TTC_TIMER select HAVE_ARM_SCU if SMP select HAVE_ARM_TWD if SMP select ICST - select CADENCE_TTC_TIMER - select ARM_GLOBAL_TIMER if !CPU_FREQ select MFD_SYSCON + select SOC_BUS 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 6fcc584c1a11..edbd9d83f407 100644 --- a/arch/arm/mach-zynq/common.c +++ b/arch/arm/mach-zynq/common.c @@ -29,6 +29,8 @@ #include <linux/memblock.h> #include <linux/irqchip.h> #include <linux/irqchip/arm-gic.h> +#include <linux/slab.h> +#include <linux/sys_soc.h> #include <asm/mach/arch.h> #include <asm/mach/map.h> @@ -37,10 +39,15 @@ #include <asm/page.h> #include <asm/pgtable.h> #include <asm/smp_scu.h> +#include <asm/system_info.h> #include <asm/hardware/cache-l2x0.h> #include "common.h" +#define ZYNQ_DEVCFG_MCTRL 0x80 +#define ZYNQ_DEVCFG_PS_VERSION_SHIFT 28 +#define ZYNQ_DEVCFG_PS_VERSION_MASK 0xF + void __iomem *zynq_scu_base; /** @@ -60,19 +67,81 @@ static struct platform_device zynq_cpuidle_device = { }; /** + * zynq_get_revision - Get Zynq silicon revision + * + * Return: Silicon version or -1 otherwise + */ +static int __init zynq_get_revision(void) +{ + struct device_node *np; + void __iomem *zynq_devcfg_base; + u32 revision; + + np = of_find_compatible_node(NULL, NULL, "xlnx,zynq-devcfg-1.0"); + if (!np) { + pr_err("%s: no devcfg node found\n", __func__); + return -1; + } + + zynq_devcfg_base = of_iomap(np, 0); + if (!zynq_devcfg_base) { + pr_err("%s: Unable to map I/O memory\n", __func__); + return -1; + } + + revision = readl(zynq_devcfg_base + ZYNQ_DEVCFG_MCTRL); + revision >>= ZYNQ_DEVCFG_PS_VERSION_SHIFT; + revision &= ZYNQ_DEVCFG_PS_VERSION_MASK; + + iounmap(zynq_devcfg_base); + + return revision; +} + +/** * zynq_init_machine - System specific initialization, intended to be * called from board specific initialization. */ static void __init zynq_init_machine(void) { struct platform_device_info devinfo = { .name = "cpufreq-cpu0", }; + struct soc_device_attribute *soc_dev_attr; + struct soc_device *soc_dev; + struct device *parent = NULL; /* * 64KB way size, 8-way associativity, parity disabled */ l2x0_of_init(0x02060000, 0xF0F0FFFF); - of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) + goto out; + + system_rev = zynq_get_revision(); + + soc_dev_attr->family = kasprintf(GFP_KERNEL, "Xilinx Zynq"); + soc_dev_attr->revision = kasprintf(GFP_KERNEL, "0x%x", system_rev); + soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "0x%x", + zynq_slcr_get_device_id()); + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + kfree(soc_dev_attr->family); + kfree(soc_dev_attr->revision); + kfree(soc_dev_attr->soc_id); + kfree(soc_dev_attr); + goto out; + } + + parent = soc_device_to_device(soc_dev); + +out: + /* + * Finished with the static registrations now; fill in the missing + * devices + */ + of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); platform_device_register(&zynq_cpuidle_device); platform_device_register_full(&devinfo); diff --git a/arch/arm/mach-zynq/common.h b/arch/arm/mach-zynq/common.h index b097844d3175..f652f0a884a6 100644 --- a/arch/arm/mach-zynq/common.h +++ b/arch/arm/mach-zynq/common.h @@ -24,6 +24,7 @@ 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); +extern u32 zynq_slcr_get_device_id(void); #ifdef CONFIG_SMP extern void secondary_startup(void); diff --git a/arch/arm/mach-zynq/headsmp.S b/arch/arm/mach-zynq/headsmp.S index 57a32869f0aa..dd8c071941e7 100644 --- a/arch/arm/mach-zynq/headsmp.S +++ b/arch/arm/mach-zynq/headsmp.S @@ -8,9 +8,12 @@ */ #include <linux/linkage.h> #include <linux/init.h> +#include <asm/assembler.h> ENTRY(zynq_secondary_trampoline) - ldr r0, [pc] +ARM_BE8(setend be) @ ensure we are in BE8 mode + ldr r0, zynq_secondary_trampoline_jump +ARM_BE8(rev r0, r0) bx r0 .globl zynq_secondary_trampoline_jump zynq_secondary_trampoline_jump: diff --git a/arch/arm/mach-zynq/slcr.c b/arch/arm/mach-zynq/slcr.c index a37d49a6e657..c43a2d16e223 100644 --- a/arch/arm/mach-zynq/slcr.c +++ b/arch/arm/mach-zynq/slcr.c @@ -26,10 +26,13 @@ #define SLCR_PS_RST_CTRL_OFFSET 0x200 /* PS Software Reset Control */ #define SLCR_A9_CPU_RST_CTRL_OFFSET 0x244 /* CPU Software Reset Control */ #define SLCR_REBOOT_STATUS_OFFSET 0x258 /* PS Reboot Status */ +#define SLCR_PSS_IDCODE 0x530 /* PS IDCODE */ #define SLCR_UNLOCK_MAGIC 0xDF0D #define SLCR_A9_CPU_CLKSTOP 0x10 #define SLCR_A9_CPU_RST 0x1 +#define SLCR_PSS_IDCODE_DEVICE_SHIFT 12 +#define SLCR_PSS_IDCODE_DEVICE_MASK 0x1F static void __iomem *zynq_slcr_base; static struct regmap *zynq_slcr_regmap; @@ -83,6 +86,22 @@ static inline int zynq_slcr_unlock(void) } /** + * zynq_slcr_get_device_id - Read device code id + * + * Return: Device code id + */ +u32 zynq_slcr_get_device_id(void) +{ + u32 val; + + zynq_slcr_read(&val, SLCR_PSS_IDCODE); + val >>= SLCR_PSS_IDCODE_DEVICE_SHIFT; + val &= SLCR_PSS_IDCODE_DEVICE_MASK; + + return val; +} + +/** * zynq_slcr_system_reset - Reset the entire system. */ void zynq_slcr_system_reset(void) |