* [PATCH 1/2] scsi: ufs: Prepare to add HCI capabilities sysfs
2024-07-31 12:20 [PATCH 0/2] scsi: ufs: Add host capabilities sysfs group Avri Altman
@ 2024-07-31 12:20 ` Avri Altman
2024-07-31 12:20 ` [PATCH 2/2] scsi: ufs: Add HCI capabilities sysfs group Avri Altman
1 sibling, 0 replies; 5+ messages in thread
From: Avri Altman @ 2024-07-31 12:20 UTC (permalink / raw)
To: Martin K . Petersen; +Cc: linux-scsi, linux-kernel, Avri Altman
Prepare so we'll be able to read various other HCI registers.
While at it, fix the HCPID & HCMID register names to stand for what they
really are.
Signed-off-by: Avri Altman <avri.altman@wdc.com>
---
drivers/ufs/core/ufs-sysfs.c | 38 +++++++++++++++++++++---------------
include/ufs/ufshci.h | 5 +++--
2 files changed, 25 insertions(+), 18 deletions(-)
diff --git a/drivers/ufs/core/ufs-sysfs.c b/drivers/ufs/core/ufs-sysfs.c
index e80a32421a8c..7a264f8ef140 100644
--- a/drivers/ufs/core/ufs-sysfs.c
+++ b/drivers/ufs/core/ufs-sysfs.c
@@ -198,33 +198,39 @@ static u32 ufshcd_us_to_ahit(unsigned int timer)
FIELD_PREP(UFSHCI_AHIBERN8_SCALE_MASK, scale);
}
-static ssize_t auto_hibern8_show(struct device *dev,
- struct device_attribute *attr, char *buf)
+static int ufshcd_read_hci_reg(struct ufs_hba *hba, u32 *val, unsigned int reg)
{
- u32 ahit;
- int ret;
- struct ufs_hba *hba = dev_get_drvdata(dev);
-
- if (!ufshcd_is_auto_hibern8_supported(hba))
- return -EOPNOTSUPP;
-
down(&hba->host_sem);
if (!ufshcd_is_user_access_allowed(hba)) {
- ret = -EBUSY;
- goto out;
+ up(&hba->host_sem);
+ return -EBUSY;
}
pm_runtime_get_sync(hba->dev);
ufshcd_hold(hba);
- ahit = ufshcd_readl(hba, REG_AUTO_HIBERNATE_IDLE_TIMER);
+ *val = ufshcd_readl(hba, reg);
ufshcd_release(hba);
pm_runtime_put_sync(hba->dev);
- ret = sysfs_emit(buf, "%d\n", ufshcd_ahit_to_us(ahit));
-
-out:
up(&hba->host_sem);
- return ret;
+ return 0;
+}
+
+static ssize_t auto_hibern8_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ u32 ahit;
+ int ret;
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+
+ if (!ufshcd_is_auto_hibern8_supported(hba))
+ return -EOPNOTSUPP;
+
+ ret = ufshcd_read_hci_reg(hba, &ahit, REG_AUTO_HIBERNATE_IDLE_TIMER);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%d\n", ufshcd_ahit_to_us(ahit));
}
static ssize_t auto_hibern8_store(struct device *dev,
diff --git a/include/ufs/ufshci.h b/include/ufs/ufshci.h
index 38fe97971a65..194e3655902e 100644
--- a/include/ufs/ufshci.h
+++ b/include/ufs/ufshci.h
@@ -25,8 +25,9 @@ enum {
REG_CONTROLLER_CAPABILITIES = 0x00,
REG_MCQCAP = 0x04,
REG_UFS_VERSION = 0x08,
- REG_CONTROLLER_DEV_ID = 0x10,
- REG_CONTROLLER_PROD_ID = 0x14,
+ REG_EXT_CONTROLLER_CAPABILITIES = 0x0C,
+ REG_CONTROLLER_PID = 0x10,
+ REG_CONTROLLER_MID = 0x14,
REG_AUTO_HIBERNATE_IDLE_TIMER = 0x18,
REG_INTERRUPT_STATUS = 0x20,
REG_INTERRUPT_ENABLE = 0x24,
--
2.25.1
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH 2/2] scsi: ufs: Add HCI capabilities sysfs group
2024-07-31 12:20 [PATCH 0/2] scsi: ufs: Add host capabilities sysfs group Avri Altman
2024-07-31 12:20 ` [PATCH 1/2] scsi: ufs: Prepare to add HCI capabilities sysfs Avri Altman
@ 2024-07-31 12:20 ` Avri Altman
2024-07-31 21:13 ` Bart Van Assche
1 sibling, 1 reply; 5+ messages in thread
From: Avri Altman @ 2024-07-31 12:20 UTC (permalink / raw)
To: Martin K . Petersen; +Cc: linux-scsi, linux-kernel, Avri Altman
The standard register map of UFSHCI is comprised of several groups. The
first group (starting from offset 0x00), is the host capabilities group.
It contains some interesting information, that otherwise is not
available, e.g. the UFS version of the platform etc.
Signed-off-by: Avri Altman <avri.altman@wdc.com>
---
drivers/ufs/core/ufs-sysfs.c | 95 ++++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+)
diff --git a/drivers/ufs/core/ufs-sysfs.c b/drivers/ufs/core/ufs-sysfs.c
index 7a264f8ef140..9ec3fc2f3af4 100644
--- a/drivers/ufs/core/ufs-sysfs.c
+++ b/drivers/ufs/core/ufs-sysfs.c
@@ -525,6 +525,100 @@ static const struct attribute_group ufs_sysfs_capabilities_group = {
.attrs = ufs_sysfs_capabilities_attrs,
};
+static ssize_t capabilities_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "0x%x\n", hba->capabilities);
+}
+
+static ssize_t mcq_cap_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+
+ if (hba->ufs_version < ufshci_version(4, 0))
+ return -EOPNOTSUPP;
+
+ return sysfs_emit(buf, "0x%x\n", hba->mcq_capabilities);
+}
+
+static ssize_t version_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "0x%x\n", hba->ufs_version);
+}
+
+static ssize_t ext_capabilities_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret;
+ u32 val;
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+
+ if (hba->ufs_version < ufshci_version(4, 0))
+ return -EOPNOTSUPP;
+
+ ret = ufshcd_read_hci_reg(hba, &val, REG_EXT_CONTROLLER_CAPABILITIES);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "0x%x\n", val);
+}
+
+static ssize_t product_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret;
+ u32 val;
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+
+ ret = ufshcd_read_hci_reg(hba, &val, REG_CONTROLLER_PID);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "0x%x\n", val);
+}
+
+static ssize_t man_id_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int ret;
+ u32 val;
+ struct ufs_hba *hba = dev_get_drvdata(dev);
+
+ ret = ufshcd_read_hci_reg(hba, &val, REG_CONTROLLER_MID);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "0x%x\n", val);
+}
+
+static DEVICE_ATTR_RO(capabilities);
+static DEVICE_ATTR_RO(mcq_cap);
+static DEVICE_ATTR_RO(version);
+static DEVICE_ATTR_RO(ext_capabilities);
+static DEVICE_ATTR_RO(product_id);
+static DEVICE_ATTR_RO(man_id);
+
+static struct attribute *ufs_sysfs_ufshci_cap_attrs[] = {
+ &dev_attr_capabilities.attr,
+ &dev_attr_mcq_cap.attr,
+ &dev_attr_version.attr,
+ &dev_attr_ext_capabilities.attr,
+ &dev_attr_product_id.attr,
+ &dev_attr_man_id.attr,
+ NULL
+};
+
+static const struct attribute_group ufs_sysfs_ufshci_group = {
+ .name = "ufshci_capabilities",
+ .attrs = ufs_sysfs_ufshci_cap_attrs,
+};
+
static ssize_t monitor_enable_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
@@ -1508,6 +1602,7 @@ static const struct attribute_group ufs_sysfs_attributes_group = {
static const struct attribute_group *ufs_sysfs_groups[] = {
&ufs_sysfs_default_group,
&ufs_sysfs_capabilities_group,
+ &ufs_sysfs_ufshci_group,
&ufs_sysfs_monitor_group,
&ufs_sysfs_power_info_group,
&ufs_sysfs_device_descriptor_group,
--
2.25.1
^ permalink raw reply [flat|nested] 5+ messages in thread