ARM: imx6: report soc info via soc device
authorShawn Guo <shawn.guo@linaro.org>
Tue, 13 Aug 2013 08:59:28 +0000 (16:59 +0800)
committerShawn Guo <shawn.guo@linaro.org>
Mon, 21 Oct 2013 01:14:54 +0000 (09:14 +0800)
The patch enables soc bus infrastructure and adds a function
imx_soc_device_init() to report soc info via soc device interface for
imx6qdl and imx6sl.  With the support, user space can get soc related
info by looking at sysfs like below.

  $ cat /sys/devices/soc0/machine
  Freescale i.MX6 Quad SABRE Smart Device Board
  $ cat /sys/devices/soc0/family
  Freescale i.MX
  $ cat /sys/devices/soc0/soc_id
  i.MX6Q
  $ cat /sys/devices/soc0/revision
  1.2

Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/common.h
arch/arm/mach-imx/cpu.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mach-imx6sl.c
arch/arm/mach-imx/mxc.h

index 9f67338ac2ee4e17150134328733277fc0098ddd..e0179158aec6765496e14f7c0deaf5bd36200adf 100644 (file)
@@ -11,6 +11,7 @@ config ARCH_MXC
        select GENERIC_IRQ_CHIP
        select MIGHT_HAVE_CACHE_L2X0 if ARCH_MULTI_V6_V7
        select MULTI_IRQ_HANDLER
+       select SOC_BUS
        select SPARSE_IRQ
        select USE_OF
        help
index d0191152807d23ed5f2bf3a427f0ab97284659cf..f9d01142a4f6a34027f4ffca933c4fa223bf6530 100644 (file)
@@ -79,6 +79,7 @@ extern int mxc_device_init(void);
 void imx_set_soc_revision(unsigned int rev);
 unsigned int imx_get_soc_revision(void);
 void imx_init_revision_from_anatop(void);
+struct device *imx_soc_device_init(void);
 
 enum mxc_cpu_pwr_mode {
        WAIT_CLOCKED,           /* wfi only */
index 51f6c51ca8783ed6fbac57cf7ca92723c89b8109..fae2c9a787441540ad586f438024f44dd8c74c9a 100644 (file)
@@ -1,6 +1,9 @@
 
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
 
 #include "hardware.h"
 #include "common.h"
@@ -56,3 +59,81 @@ void __init imx_set_aips(void __iomem *base)
        reg = __raw_readl(base + 0x50) & 0x00FFFFFF;
        __raw_writel(reg, base + 0x50);
 }
+
+struct device * __init imx_soc_device_init(void)
+{
+       struct soc_device_attribute *soc_dev_attr;
+       struct soc_device *soc_dev;
+       struct device_node *root;
+       const char *soc_id;
+       int ret;
+
+       soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+       if (!soc_dev_attr)
+               return NULL;
+
+       soc_dev_attr->family = "Freescale i.MX";
+
+       root = of_find_node_by_path("/");
+       ret = of_property_read_string(root, "model", &soc_dev_attr->machine);
+       of_node_put(root);
+       if (ret)
+               goto free_soc;
+
+       switch (__mxc_cpu_type) {
+       case MXC_CPU_MX1:
+               soc_id = "i.MX1";
+               break;
+       case MXC_CPU_MX21:
+               soc_id = "i.MX21";
+               break;
+       case MXC_CPU_MX25:
+               soc_id = "i.MX25";
+               break;
+       case MXC_CPU_MX27:
+               soc_id = "i.MX27";
+               break;
+       case MXC_CPU_MX31:
+               soc_id = "i.MX31";
+               break;
+       case MXC_CPU_MX35:
+               soc_id = "i.MX35";
+               break;
+       case MXC_CPU_MX51:
+               soc_id = "i.MX51";
+               break;
+       case MXC_CPU_MX53:
+               soc_id = "i.MX53";
+               break;
+       case MXC_CPU_IMX6SL:
+               soc_id = "i.MX6SL";
+               break;
+       case MXC_CPU_IMX6DL:
+               soc_id = "i.MX6DL";
+               break;
+       case MXC_CPU_IMX6Q:
+               soc_id = "i.MX6Q";
+               break;
+       default:
+               soc_id = "Unknown";
+       }
+       soc_dev_attr->soc_id = soc_id;
+
+       soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d.%d",
+                                          (imx_soc_revision >> 4) & 0xf,
+                                          imx_soc_revision & 0xf);
+       if (!soc_dev_attr->revision)
+               goto free_soc;
+
+       soc_dev = soc_device_register(soc_dev_attr);
+       if (IS_ERR(soc_dev))
+               goto free_rev;
+
+       return soc_device_to_device(soc_dev);
+
+free_rev:
+       kfree(soc_dev_attr->revision);
+free_soc:
+       kfree(soc_dev_attr);
+       return NULL;
+}
index 1bdd0be429b93cc93988cf4c3ae2e9e9dce760cb..049e36edc143e87f7ef8ee9da2ebdf7d87cdfd67 100644 (file)
@@ -162,12 +162,18 @@ static void __init imx6q_1588_init(void)
 
 static void __init imx6q_init_machine(void)
 {
+       struct device *parent;
+
        imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
                              imx_get_soc_revision());
 
+       parent = imx_soc_device_init();
+       if (parent == NULL)
+               pr_warn("failed to initialize soc device\n");
+
        imx6q_enet_phy_init();
 
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
 
        imx_anatop_init();
        imx6q_pm_init();
index 4ce9ae58ed0c704255e2fee5dc387cfa37c2a9cf..f01aaabd325464c0995465f6c281d2c1a1ba33cd 100644 (file)
@@ -36,9 +36,15 @@ static void __init imx6sl_fec_init(void)
 
 static void __init imx6sl_init_machine(void)
 {
+       struct device *parent;
+
        mxc_arch_reset_init_dt();
 
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+       parent = imx_soc_device_init();
+       if (parent == NULL)
+               pr_warn("failed to initialize soc device\n");
+
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
 
        imx6sl_fec_init();
 }
index 8629e5be7ecd19f665a13a10a554d4b3bedab00f..99e03ea9bf79f9e516522522bd87f4268718aaf9 100644 (file)
@@ -34,6 +34,7 @@
 #define MXC_CPU_MX35           35
 #define MXC_CPU_MX51           51
 #define MXC_CPU_MX53           53
+#define MXC_CPU_IMX6SL         0x60
 #define MXC_CPU_IMX6DL         0x61
 #define MXC_CPU_IMX6Q          0x63