@@ -20,6 +20,11 @@ struct fsl_soc_die_attr {
u32 mask;
};
+struct fsl_soc_data {
+ const char *sfp_compat;
+ u32 uid_offset;
+};
+
/* SoC die attribute definition for QorIQ platform */
static const struct fsl_soc_die_attr fsl_soc_die[] = {
/*
@@ -110,6 +115,33 @@ static const struct fsl_soc_die_attr *fsl_soc_die_match(
return NULL;
}
+static u64 fsl_guts_get_soc_uid(const char *compat, unsigned int offset)
+{
+ struct device_node *np;
+ void __iomem *sfp_base;
+ u64 uid;
+
+ np = of_find_compatible_node(NULL, NULL, compat);
+ if (!np)
+ return 0;
+
+ sfp_base = of_iomap(np, 0);
+
+ uid = ioread32(sfp_base + offset);
+ uid <<= 32;
+ uid |= ioread32(sfp_base + offset + 4);
+
+ iounmap(sfp_base);
+ of_node_put(np);
+
+ return uid;
+}
+
+static const struct fsl_soc_data ls1028a_data = {
+ .sfp_compat = "fsl,ls1028a-sfp",
+ .uid_offset = 0x21c,
+};
+
/*
* Table for matching compatible strings, for device tree
* guts node, for Freescale QorIQ SOCs.
@@ -138,7 +170,7 @@ static const struct of_device_id fsl_guts_of_match[] = {
{ .compatible = "fsl,ls1012a-dcfg", },
{ .compatible = "fsl,ls1046a-dcfg", },
{ .compatible = "fsl,lx2160a-dcfg", },
- { .compatible = "fsl,ls1028a-dcfg", },
+ { .compatible = "fsl,ls1028a-dcfg", .data = &ls1028a_data},
{}
};
@@ -147,16 +179,20 @@ static int __init fsl_guts_init(void)
struct soc_device_attribute *soc_dev_attr;
static struct soc_device *soc_dev;
const struct fsl_soc_die_attr *soc_die;
+ const struct fsl_soc_data *soc_data;
+ const struct of_device_id *match;
struct ccsr_guts __iomem *regs;
const char *machine = NULL;
struct device_node *np;
bool little_endian;
+ u64 soc_uid = 0;
u32 svr;
int ret;
- np = of_find_matching_node_and_match(NULL, fsl_guts_of_match, NULL);
+ np = of_find_matching_node_and_match(NULL, fsl_guts_of_match, &match);
if (!np)
return 0;
+ soc_data = match->data;
regs = of_iomap(np, 0);
if (IS_ERR(regs)) {
@@ -204,6 +240,13 @@ static int __init fsl_guts_init(void)
if (!soc_dev_attr->revision)
goto err_nomem;
+ if (soc_data)
+ soc_uid = fsl_guts_get_soc_uid(soc_data->sfp_compat,
+ soc_data->uid_offset);
+ if (soc_uid)
+ soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX",
+ soc_uid);
+
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
ret = PTR_ERR(soc_dev);
@@ -224,6 +267,7 @@ static int __init fsl_guts_init(void)
kfree(soc_dev_attr->family);
kfree(soc_dev_attr->soc_id);
kfree(soc_dev_attr->revision);
+ kfree(soc_dev_attr->serial_number);
kfree(soc_dev_attr);
return ret;