|
@@ -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;
|
|
|
|
|
|
/**
|
|
@@ -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.
|
|
@@ -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);
|