Commit 86aa1608 authored by Arnd Bergmann's avatar Arnd Bergmann

Merge tag 'soc-attr-updates-5.9' of...

Merge tag 'soc-attr-updates-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux into arm/drivers

SoC attributes update for v5.9

1. Addition of ARM SMCCC ARCH_SOC_ID support
2. Usage of the custom soc attribute groups already supported in the
   infrastucture instead of device_create_file which eliminates the need
   for any cleanup when soc is unregistered
3. Minor clean up switching to use standard DEVICE_ATTR_RO() instead of
   direct __ATTR

* tag 'soc-attr-updates-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/sudeep.holla/linux:
  firmware: smccc: Add ARCH_SOC_ID support
  ARM: OMAP2: Use custom soc attribute group instead of device_create_file
  ARM: OMAP2: Switch to use DEVICE_ATTR_RO()
  soc: ux500: Use custom soc attribute group instead of device_create_file
  soc: ux500: Switch to use DEVICE_ATTR_RO()
  soc: integrator: Use custom soc attribute group instead of device_create_file
  soc: integrator: Switch to use DEVICE_ATTR_RO()
  soc: realview: Use custom soc attribute group instead of device_create_file
  soc: realview: Switch to use DEVICE_ATTR_RO()

Link: https://lore.kernel.org/r/20200706165312.40697-1-sudeep.holla@arm.comSigned-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 48778464 821b67fa
...@@ -26,6 +26,30 @@ Description: ...@@ -26,6 +26,30 @@ Description:
Read-only attribute common to all SoCs. Contains SoC family name Read-only attribute common to all SoCs. Contains SoC family name
(e.g. DB8500). (e.g. DB8500).
On many of ARM based silicon with SMCCC v1.2+ compliant firmware
this will contain the JEDEC JEP106 manufacturer’s identification
code. The format is "jep106:XXYY" where XX is identity code and
YY is continuation code.
This manufacturer’s identification code is defined by one
or more eight (8) bit fields, each consisting of seven (7)
data bits plus one (1) odd parity bit. It is a single field,
limiting the possible number of vendors to 126. To expand
the maximum number of identification codes, a continuation
scheme has been defined.
The specified mechanism is that an identity code of 0x7F
represents the "continuation code" and implies the presence
of an additional identity code field, and this mechanism
may be extended to multiple continuation codes followed
by the manufacturer's identity code.
For example, ARM has identity code 0x7F 0x7F 0x7F 0x7F 0x3B,
which is code 0x3B on the fifth 'page'. This is shortened
as JEP106 identity code of 0x3B and a continuation code of
0x4 to represent the four continuation codes preceding the
identity code.
What: /sys/devices/socX/serial_number What: /sys/devices/socX/serial_number
Date: January 2019 Date: January 2019
contact: Bjorn Andersson <bjorn.andersson@linaro.org> contact: Bjorn Andersson <bjorn.andersson@linaro.org>
...@@ -40,6 +64,12 @@ Description: ...@@ -40,6 +64,12 @@ Description:
Read-only attribute supported by most SoCs. In the case of Read-only attribute supported by most SoCs. In the case of
ST-Ericsson's chips this contains the SoC serial number. ST-Ericsson's chips this contains the SoC serial number.
On many of ARM based silicon with SMCCC v1.2+ compliant firmware
this will contain the SOC ID appended to the family attribute
to ensure there is no conflict in this namespace across various
vendors. The format is "jep106:XXYY:ZZZZ" where XX is identity
code, YY is continuation code and ZZZZ is the SOC ID.
What: /sys/devices/socX/revision What: /sys/devices/socX/revision
Date: January 2012 Date: January 2012
contact: Lee Jones <lee.jones@linaro.org> contact: Lee Jones <lee.jones@linaro.org>
......
...@@ -775,19 +775,23 @@ static const char * __init omap_get_family(void) ...@@ -775,19 +775,23 @@ static const char * __init omap_get_family(void)
return kasprintf(GFP_KERNEL, "Unknown"); return kasprintf(GFP_KERNEL, "Unknown");
} }
static ssize_t omap_get_type(struct device *dev, static ssize_t
struct device_attribute *attr, type_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%s\n", omap_types[omap_type()]); return sprintf(buf, "%s\n", omap_types[omap_type()]);
} }
static struct device_attribute omap_soc_attr = static DEVICE_ATTR_RO(type);
__ATTR(type, S_IRUGO, omap_get_type, NULL);
static struct attribute *omap_soc_attrs[] = {
&dev_attr_type.attr,
NULL
};
ATTRIBUTE_GROUPS(omap_soc);
void __init omap_soc_device_init(void) void __init omap_soc_device_init(void)
{ {
struct device *parent;
struct soc_device *soc_dev; struct soc_device *soc_dev;
struct soc_device_attribute *soc_dev_attr; struct soc_device_attribute *soc_dev_attr;
...@@ -798,14 +802,12 @@ void __init omap_soc_device_init(void) ...@@ -798,14 +802,12 @@ void __init omap_soc_device_init(void)
soc_dev_attr->machine = soc_name; soc_dev_attr->machine = soc_name;
soc_dev_attr->family = omap_get_family(); soc_dev_attr->family = omap_get_family();
soc_dev_attr->revision = soc_rev; soc_dev_attr->revision = soc_rev;
soc_dev_attr->custom_attr_group = omap_soc_groups[0];
soc_dev = soc_device_register(soc_dev_attr); soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) { if (IS_ERR(soc_dev)) {
kfree(soc_dev_attr); kfree(soc_dev_attr);
return; return;
} }
parent = soc_device_to_device(soc_dev);
device_create_file(parent, &omap_soc_attr);
} }
#endif /* CONFIG_SOC_BUS */ #endif /* CONFIG_SOC_BUS */
...@@ -14,3 +14,12 @@ config HAVE_ARM_SMCCC_DISCOVERY ...@@ -14,3 +14,12 @@ config HAVE_ARM_SMCCC_DISCOVERY
to add SMCCC discovery mechanism though the PSCI firmware to add SMCCC discovery mechanism though the PSCI firmware
implementation of PSCI_FEATURES(SMCCC_VERSION) which returns implementation of PSCI_FEATURES(SMCCC_VERSION) which returns
success on firmware compliant to SMCCC v1.1 and above. success on firmware compliant to SMCCC v1.1 and above.
config ARM_SMCCC_SOC_ID
bool "SoC bus device for the ARM SMCCC SOC_ID"
depends on HAVE_ARM_SMCCC_DISCOVERY
default y
select SOC_BUS
help
Include support for the SoC bus on the ARM SMCCC firmware based
platforms providing some sysfs information about the SoC variant.
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
# #
obj-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smccc.o obj-$(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) += smccc.o
obj-$(CONFIG_ARM_SMCCC_SOC_ID) += soc_id.o
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright 2020 Arm Limited
*/
#define pr_fmt(fmt) "SMCCC: SOC_ID: " fmt
#include <linux/arm-smccc.h>
#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sys_soc.h>
#define SMCCC_SOC_ID_JEP106_BANK_IDX_MASK GENMASK(30, 24)
/*
* As per the SMC Calling Convention specification v1.2 (ARM DEN 0028C)
* Section 7.4 SMCCC_ARCH_SOC_ID bits[23:16] are JEP-106 identification
* code with parity bit for the SiP. We can drop the parity bit.
*/
#define SMCCC_SOC_ID_JEP106_ID_CODE_MASK GENMASK(22, 16)
#define SMCCC_SOC_ID_IMP_DEF_SOC_ID_MASK GENMASK(15, 0)
#define JEP106_BANK_CONT_CODE(x) \
(u8)(FIELD_GET(SMCCC_SOC_ID_JEP106_BANK_IDX_MASK, (x)))
#define JEP106_ID_CODE(x) \
(u8)(FIELD_GET(SMCCC_SOC_ID_JEP106_ID_CODE_MASK, (x)))
#define IMP_DEF_SOC_ID(x) \
(u16)(FIELD_GET(SMCCC_SOC_ID_IMP_DEF_SOC_ID_MASK, (x)))
static struct soc_device *soc_dev;
static struct soc_device_attribute *soc_dev_attr;
static int __init smccc_soc_init(void)
{
struct arm_smccc_res res;
int soc_id_rev, soc_id_version;
static char soc_id_str[20], soc_id_rev_str[12];
static char soc_id_jep106_id_str[12];
if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2)
return 0;
if (arm_smccc_1_1_get_conduit() == SMCCC_CONDUIT_NONE) {
pr_err("%s: invalid SMCCC conduit\n", __func__);
return -EOPNOTSUPP;
}
arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
ARM_SMCCC_ARCH_SOC_ID, &res);
if (res.a0 == SMCCC_RET_NOT_SUPPORTED) {
pr_info("ARCH_SOC_ID not implemented, skipping ....\n");
return 0;
}
if ((int)res.a0 < 0) {
pr_info("ARCH_FEATURES(ARCH_SOC_ID) returned error: %lx\n",
res.a0);
return -EINVAL;
}
arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_SOC_ID, 0, &res);
if ((int)res.a0 < 0) {
pr_err("ARCH_SOC_ID(0) returned error: %lx\n", res.a0);
return -EINVAL;
}
soc_id_version = res.a0;
arm_smccc_1_1_invoke(ARM_SMCCC_ARCH_SOC_ID, 1, &res);
if ((int)res.a0 < 0) {
pr_err("ARCH_SOC_ID(1) returned error: %lx\n", res.a0);
return -EINVAL;
}
soc_id_rev = res.a0;
soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
return -ENOMEM;
sprintf(soc_id_rev_str, "0x%08x", soc_id_rev);
sprintf(soc_id_jep106_id_str, "jep106:%02x%02x",
JEP106_BANK_CONT_CODE(soc_id_version),
JEP106_ID_CODE(soc_id_version));
sprintf(soc_id_str, "%s:%04x", soc_id_jep106_id_str,
IMP_DEF_SOC_ID(soc_id_version));
soc_dev_attr->soc_id = soc_id_str;
soc_dev_attr->revision = soc_id_rev_str;
soc_dev_attr->family = soc_id_jep106_id_str;
soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) {
kfree(soc_dev_attr);
return PTR_ERR(soc_dev);
}
pr_info("ID = %s Revision = %s\n", soc_dev_attr->soc_id,
soc_dev_attr->revision);
return 0;
}
module_init(smccc_soc_init);
static void __exit smccc_soc_exit(void)
{
if (soc_dev)
soc_device_unregister(soc_dev);
kfree(soc_dev_attr);
}
module_exit(smccc_soc_exit);
...@@ -146,9 +146,8 @@ static const char * __init ux500_get_revision(void) ...@@ -146,9 +146,8 @@ static const char * __init ux500_get_revision(void)
return kasprintf(GFP_KERNEL, "%s", "Unknown"); return kasprintf(GFP_KERNEL, "%s", "Unknown");
} }
static ssize_t ux500_get_process(struct device *dev, static ssize_t
struct device_attribute *attr, process_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
if (dbx500_id.process == 0x00) if (dbx500_id.process == 0x00)
return sprintf(buf, "Standard\n"); return sprintf(buf, "Standard\n");
...@@ -156,6 +155,15 @@ static ssize_t ux500_get_process(struct device *dev, ...@@ -156,6 +155,15 @@ static ssize_t ux500_get_process(struct device *dev,
return sprintf(buf, "%02xnm\n", dbx500_id.process); return sprintf(buf, "%02xnm\n", dbx500_id.process);
} }
static DEVICE_ATTR_RO(process);
static struct attribute *ux500_soc_attrs[] = {
&dev_attr_process.attr,
NULL
};
ATTRIBUTE_GROUPS(ux500_soc);
static const char *db8500_read_soc_id(struct device_node *backupram) static const char *db8500_read_soc_id(struct device_node *backupram)
{ {
void __iomem *base; void __iomem *base;
...@@ -184,14 +192,11 @@ static void __init soc_info_populate(struct soc_device_attribute *soc_dev_attr, ...@@ -184,14 +192,11 @@ static void __init soc_info_populate(struct soc_device_attribute *soc_dev_attr,
soc_dev_attr->machine = ux500_get_machine(); soc_dev_attr->machine = ux500_get_machine();
soc_dev_attr->family = ux500_get_family(); soc_dev_attr->family = ux500_get_family();
soc_dev_attr->revision = ux500_get_revision(); soc_dev_attr->revision = ux500_get_revision();
soc_dev_attr->custom_attr_group = ux500_soc_groups[0];
} }
static const struct device_attribute ux500_soc_attr =
__ATTR(process, S_IRUGO, ux500_get_process, NULL);
static int __init ux500_soc_device_init(void) static int __init ux500_soc_device_init(void)
{ {
struct device *parent;
struct soc_device *soc_dev; struct soc_device *soc_dev;
struct soc_device_attribute *soc_dev_attr; struct soc_device_attribute *soc_dev_attr;
struct device_node *backupram; struct device_node *backupram;
...@@ -217,9 +222,6 @@ static int __init ux500_soc_device_init(void) ...@@ -217,9 +222,6 @@ static int __init ux500_soc_device_init(void)
return PTR_ERR(soc_dev); return PTR_ERR(soc_dev);
} }
parent = soc_device_to_device(soc_dev);
device_create_file(parent, &ux500_soc_attr);
return 0; return 0;
} }
subsys_initcall(ux500_soc_device_init); subsys_initcall(ux500_soc_device_init);
...@@ -56,45 +56,47 @@ static const char *integrator_fpga_str(u32 id) ...@@ -56,45 +56,47 @@ static const char *integrator_fpga_str(u32 id)
} }
} }
static ssize_t integrator_get_manf(struct device *dev, static ssize_t
struct device_attribute *attr, manufacturer_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%02x\n", integrator_coreid >> 24); return sprintf(buf, "%02x\n", integrator_coreid >> 24);
} }
static struct device_attribute integrator_manf_attr = static DEVICE_ATTR_RO(manufacturer);
__ATTR(manufacturer, S_IRUGO, integrator_get_manf, NULL);
static ssize_t integrator_get_arch(struct device *dev, static ssize_t
struct device_attribute *attr, arch_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%s\n", integrator_arch_str(integrator_coreid)); return sprintf(buf, "%s\n", integrator_arch_str(integrator_coreid));
} }
static struct device_attribute integrator_arch_attr = static DEVICE_ATTR_RO(arch);
__ATTR(arch, S_IRUGO, integrator_get_arch, NULL);
static ssize_t integrator_get_fpga(struct device *dev, static ssize_t
struct device_attribute *attr, fpga_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%s\n", integrator_fpga_str(integrator_coreid)); return sprintf(buf, "%s\n", integrator_fpga_str(integrator_coreid));
} }
static struct device_attribute integrator_fpga_attr = static DEVICE_ATTR_RO(fpga);
__ATTR(fpga, S_IRUGO, integrator_get_fpga, NULL);
static ssize_t integrator_get_build(struct device *dev, static ssize_t
struct device_attribute *attr, build_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%02x\n", (integrator_coreid >> 4) & 0xFF); return sprintf(buf, "%02x\n", (integrator_coreid >> 4) & 0xFF);
} }
static struct device_attribute integrator_build_attr = static DEVICE_ATTR_RO(build);
__ATTR(build, S_IRUGO, integrator_get_build, NULL);
static struct attribute *integrator_attrs[] = {
&dev_attr_manufacturer.attr,
&dev_attr_arch.attr,
&dev_attr_fpga.attr,
&dev_attr_build.attr,
NULL
};
ATTRIBUTE_GROUPS(integrator);
static int __init integrator_soc_init(void) static int __init integrator_soc_init(void)
{ {
...@@ -127,6 +129,7 @@ static int __init integrator_soc_init(void) ...@@ -127,6 +129,7 @@ static int __init integrator_soc_init(void)
soc_dev_attr->soc_id = "Integrator"; soc_dev_attr->soc_id = "Integrator";
soc_dev_attr->machine = "Integrator"; soc_dev_attr->machine = "Integrator";
soc_dev_attr->family = "Versatile"; soc_dev_attr->family = "Versatile";
soc_dev_attr->custom_attr_group = integrator_groups[0];
soc_dev = soc_device_register(soc_dev_attr); soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) { if (IS_ERR(soc_dev)) {
kfree(soc_dev_attr); kfree(soc_dev_attr);
...@@ -134,11 +137,6 @@ static int __init integrator_soc_init(void) ...@@ -134,11 +137,6 @@ static int __init integrator_soc_init(void)
} }
dev = soc_device_to_device(soc_dev); dev = soc_device_to_device(soc_dev);
device_create_file(dev, &integrator_manf_attr);
device_create_file(dev, &integrator_arch_attr);
device_create_file(dev, &integrator_fpga_attr);
device_create_file(dev, &integrator_build_attr);
dev_info(dev, "Detected ARM core module:\n"); dev_info(dev, "Detected ARM core module:\n");
dev_info(dev, " Manufacturer: %02x\n", (val >> 24)); dev_info(dev, " Manufacturer: %02x\n", (val >> 24));
dev_info(dev, " Architecture: %s\n", integrator_arch_str(val)); dev_info(dev, " Architecture: %s\n", integrator_arch_str(val));
......
...@@ -39,45 +39,47 @@ static const char *realview_arch_str(u32 id) ...@@ -39,45 +39,47 @@ static const char *realview_arch_str(u32 id)
} }
} }
static ssize_t realview_get_manf(struct device *dev, static ssize_t
struct device_attribute *attr, manufacturer_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%02x\n", realview_coreid >> 24); return sprintf(buf, "%02x\n", realview_coreid >> 24);
} }
static struct device_attribute realview_manf_attr = static DEVICE_ATTR_RO(manufacturer);
__ATTR(manufacturer, S_IRUGO, realview_get_manf, NULL);
static ssize_t realview_get_board(struct device *dev, static ssize_t
struct device_attribute *attr, board_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "HBI-%03x\n", ((realview_coreid >> 16) & 0xfff)); return sprintf(buf, "HBI-%03x\n", ((realview_coreid >> 16) & 0xfff));
} }
static struct device_attribute realview_board_attr = static DEVICE_ATTR_RO(board);
__ATTR(board, S_IRUGO, realview_get_board, NULL);
static ssize_t realview_get_arch(struct device *dev, static ssize_t
struct device_attribute *attr, fpga_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%s\n", realview_arch_str(realview_coreid)); return sprintf(buf, "%s\n", realview_arch_str(realview_coreid));
} }
static struct device_attribute realview_arch_attr = static DEVICE_ATTR_RO(fpga);
__ATTR(fpga, S_IRUGO, realview_get_arch, NULL);
static ssize_t realview_get_build(struct device *dev, static ssize_t
struct device_attribute *attr, build_show(struct device *dev, struct device_attribute *attr, char *buf)
char *buf)
{ {
return sprintf(buf, "%02x\n", (realview_coreid & 0xFF)); return sprintf(buf, "%02x\n", (realview_coreid & 0xFF));
} }
static struct device_attribute realview_build_attr = static DEVICE_ATTR_RO(build);
__ATTR(build, S_IRUGO, realview_get_build, NULL);
static struct attribute *realview_attrs[] = {
&dev_attr_manufacturer.attr,
&dev_attr_board.attr,
&dev_attr_fpga.attr,
&dev_attr_build.attr,
NULL
};
ATTRIBUTE_GROUPS(realview);
static int realview_soc_probe(struct platform_device *pdev) static int realview_soc_probe(struct platform_device *pdev)
{ {
...@@ -102,6 +104,7 @@ static int realview_soc_probe(struct platform_device *pdev) ...@@ -102,6 +104,7 @@ static int realview_soc_probe(struct platform_device *pdev)
soc_dev_attr->machine = "RealView"; soc_dev_attr->machine = "RealView";
soc_dev_attr->family = "Versatile"; soc_dev_attr->family = "Versatile";
soc_dev_attr->custom_attr_group = realview_groups[0];
soc_dev = soc_device_register(soc_dev_attr); soc_dev = soc_device_register(soc_dev_attr);
if (IS_ERR(soc_dev)) { if (IS_ERR(soc_dev)) {
kfree(soc_dev_attr); kfree(soc_dev_attr);
...@@ -112,11 +115,6 @@ static int realview_soc_probe(struct platform_device *pdev) ...@@ -112,11 +115,6 @@ static int realview_soc_probe(struct platform_device *pdev)
if (ret) if (ret)
return -ENODEV; return -ENODEV;
device_create_file(soc_device_to_device(soc_dev), &realview_manf_attr);
device_create_file(soc_device_to_device(soc_dev), &realview_board_attr);
device_create_file(soc_device_to_device(soc_dev), &realview_arch_attr);
device_create_file(soc_device_to_device(soc_dev), &realview_build_attr);
dev_info(&pdev->dev, "RealView Syscon Core ID: 0x%08x, HBI-%03x\n", dev_info(&pdev->dev, "RealView Syscon Core ID: 0x%08x, HBI-%03x\n",
realview_coreid, realview_coreid,
((realview_coreid >> 16) & 0xfff)); ((realview_coreid >> 16) & 0xfff));
......
...@@ -71,6 +71,11 @@ ...@@ -71,6 +71,11 @@
ARM_SMCCC_SMC_32, \ ARM_SMCCC_SMC_32, \
0, 1) 0, 1)
#define ARM_SMCCC_ARCH_SOC_ID \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_32, \
0, 2)
#define ARM_SMCCC_ARCH_WORKAROUND_1 \ #define ARM_SMCCC_ARCH_WORKAROUND_1 \
ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
ARM_SMCCC_SMC_32, \ ARM_SMCCC_SMC_32, \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment