ARM: clps711x: Add SOC BUS support
authorAlexander Shiyan <shc_work@mail.ru>
Tue, 19 Aug 2014 12:31:15 +0000 (16:31 +0400)
committerArnd Bergmann <arnd@arndb.de>
Thu, 4 Sep 2014 19:40:43 +0000 (21:40 +0200)
Add SOC BUS support with CPU family, machine name and unique ID.

Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
arch/arm/Kconfig
arch/arm/mach-clps711x/devices.c

index c49a775..c848172 100644 (file)
@@ -387,6 +387,7 @@ config ARCH_CLPS711X
        select CPU_ARM720T
        select GENERIC_CLOCKEVENTS
        select MFD_SYSCON
+       select SOC_BUS
        help
          Support for Cirrus Logic 711x/721x/731x based boards.
 
index 0c689d3..77a9617 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  CLPS711X common devices definitions
  *
- *  Author: Alexander Shiyan <shc_work@mail.ru>, 2013
+ *  Author: Alexander Shiyan <shc_work@mail.ru>, 2013-2014
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -9,8 +9,15 @@
  * (at your option) any later version.
  */
 
+#include <linux/io.h>
+#include <linux/of_fdt.h>
 #include <linux/platform_device.h>
+#include <linux/random.h>
 #include <linux/sizes.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+
+#include <asm/system_info.h>
 
 #include <mach/hardware.h>
 
@@ -90,10 +97,53 @@ static void __init clps711x_add_uart(void)
                                        ARRAY_SIZE(clps711x_uart2_res));
 };
 
+static void __init clps711x_soc_init(void)
+{
+       struct soc_device_attribute *soc_dev_attr;
+       struct soc_device *soc_dev;
+       void __iomem *base;
+       u32 id[5];
+
+       base = ioremap(CLPS711X_PHYS_BASE, SZ_32K);
+       if (!base)
+               return;
+
+       id[0] = readl(base + UNIQID);
+       id[1] = readl(base + RANDID0);
+       id[2] = readl(base + RANDID1);
+       id[3] = readl(base + RANDID2);
+       id[4] = readl(base + RANDID3);
+       system_rev = SYSFLG1_VERID(readl(base + SYSFLG1));
+
+       add_device_randomness(id, sizeof(id));
+
+       system_serial_low = id[0];
+
+       soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+       if (!soc_dev_attr)
+               goto out_unmap;
+
+       soc_dev_attr->machine = of_flat_dt_get_machine_name();
+       soc_dev_attr->family = "Cirrus Logic CLPS711X";
+       soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%u", system_rev);
+       soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%08x", id[0]);
+
+       soc_dev = soc_device_register(soc_dev_attr);
+       if (IS_ERR(soc_dev)) {
+               kfree(soc_dev_attr->revision);
+               kfree(soc_dev_attr->soc_id);
+               kfree(soc_dev_attr);
+       }
+
+out_unmap:
+       iounmap(base);
+}
+
 void __init clps711x_devices_init(void)
 {
        clps711x_add_cpuidle();
        clps711x_add_gpio();
        clps711x_add_syscon();
        clps711x_add_uart();
+       clps711x_soc_init();
 }