Loading arch/arm/boot/dts/zynq-7000.dtsi +5 −0 Original line number Diff line number Diff line Loading @@ -154,6 +154,11 @@ clkc: clkc@100 { }; }; 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>; Loading arch/arm/mach-zynq/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -10,5 +10,6 @@ config ARCH_ZYNQ 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 arch/arm/mach-zynq/common.c +70 −1 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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; /** Loading @@ -59,6 +66,38 @@ static struct platform_device zynq_cpuidle_device = { .name = "cpuidle-zynq", }; /** * 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. Loading @@ -66,13 +105,43 @@ static struct platform_device zynq_cpuidle_device = { 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); Loading arch/arm/mach-zynq/common.h +1 −0 Original line number Diff line number Diff line Loading @@ -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); Loading arch/arm/mach-zynq/slcr.c +19 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -82,6 +85,22 @@ static inline int zynq_slcr_unlock(void) return 0; } /** * 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. */ Loading Loading
arch/arm/boot/dts/zynq-7000.dtsi +5 −0 Original line number Diff line number Diff line Loading @@ -154,6 +154,11 @@ clkc: clkc@100 { }; }; 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>; Loading
arch/arm/mach-zynq/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -10,5 +10,6 @@ config ARCH_ZYNQ 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
arch/arm/mach-zynq/common.c +70 −1 Original line number Diff line number Diff line Loading @@ -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> Loading @@ -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; /** Loading @@ -59,6 +66,38 @@ static struct platform_device zynq_cpuidle_device = { .name = "cpuidle-zynq", }; /** * 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. Loading @@ -66,13 +105,43 @@ static struct platform_device zynq_cpuidle_device = { 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); Loading
arch/arm/mach-zynq/common.h +1 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
arch/arm/mach-zynq/slcr.c +19 −0 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -82,6 +85,22 @@ static inline int zynq_slcr_unlock(void) return 0; } /** * 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. */ Loading