From d2ad5ac1cda7c30c9ded04d0e21aba528f1f96ec Mon Sep 17 00:00:00 2001 From: Wu Hao Date: Sun, 4 Aug 2019 18:20:13 +0800 Subject: fpga: dfl: afu: add AFU state related sysfs interfaces This patch introduces more sysfs interfaces for Accelerated Function Unit (AFU). These interfaces allow users to read current AFU Power State (APx), read / clear AFU Power (APx) events which are sticky to identify transient APx state, and manage AFU's LTR (latency tolerance reporting). Signed-off-by: Ananda Ravuri Signed-off-by: Xu Yilun Signed-off-by: Wu Hao Acked-by: Alan Tull Signed-off-by: Moritz Fischer Link: https://lore.kernel.org/r/1564914022-3710-4-git-send-email-hao.wu@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/fpga/dfl-afu-main.c | 137 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) (limited to 'drivers/fpga/dfl-afu-main.c') diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c index 68b4d0874b93..12175bbd90c1 100644 --- a/drivers/fpga/dfl-afu-main.c +++ b/drivers/fpga/dfl-afu-main.c @@ -141,8 +141,145 @@ id_show(struct device *dev, struct device_attribute *attr, char *buf) } static DEVICE_ATTR_RO(id); +static ssize_t +ltr_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); + void __iomem *base; + u64 v; + + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); + + mutex_lock(&pdata->lock); + v = readq(base + PORT_HDR_CTRL); + mutex_unlock(&pdata->lock); + + return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_CTRL_LATENCY, v)); +} + +static ssize_t +ltr_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); + void __iomem *base; + bool ltr; + u64 v; + + if (kstrtobool(buf, <r)) + return -EINVAL; + + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); + + mutex_lock(&pdata->lock); + v = readq(base + PORT_HDR_CTRL); + v &= ~PORT_CTRL_LATENCY; + v |= FIELD_PREP(PORT_CTRL_LATENCY, ltr ? 1 : 0); + writeq(v, base + PORT_HDR_CTRL); + mutex_unlock(&pdata->lock); + + return count; +} +static DEVICE_ATTR_RW(ltr); + +static ssize_t +ap1_event_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); + void __iomem *base; + u64 v; + + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); + + mutex_lock(&pdata->lock); + v = readq(base + PORT_HDR_STS); + mutex_unlock(&pdata->lock); + + return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_STS_AP1_EVT, v)); +} + +static ssize_t +ap1_event_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); + void __iomem *base; + bool clear; + + if (kstrtobool(buf, &clear) || !clear) + return -EINVAL; + + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); + + mutex_lock(&pdata->lock); + writeq(PORT_STS_AP1_EVT, base + PORT_HDR_STS); + mutex_unlock(&pdata->lock); + + return count; +} +static DEVICE_ATTR_RW(ap1_event); + +static ssize_t +ap2_event_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); + void __iomem *base; + u64 v; + + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); + + mutex_lock(&pdata->lock); + v = readq(base + PORT_HDR_STS); + mutex_unlock(&pdata->lock); + + return sprintf(buf, "%x\n", (u8)FIELD_GET(PORT_STS_AP2_EVT, v)); +} + +static ssize_t +ap2_event_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); + void __iomem *base; + bool clear; + + if (kstrtobool(buf, &clear) || !clear) + return -EINVAL; + + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); + + mutex_lock(&pdata->lock); + writeq(PORT_STS_AP2_EVT, base + PORT_HDR_STS); + mutex_unlock(&pdata->lock); + + return count; +} +static DEVICE_ATTR_RW(ap2_event); + +static ssize_t +power_state_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct dfl_feature_platform_data *pdata = dev_get_platdata(dev); + void __iomem *base; + u64 v; + + base = dfl_get_feature_ioaddr_by_id(dev, PORT_FEATURE_ID_HEADER); + + mutex_lock(&pdata->lock); + v = readq(base + PORT_HDR_STS); + mutex_unlock(&pdata->lock); + + return sprintf(buf, "0x%x\n", (u8)FIELD_GET(PORT_STS_PWR_STATE, v)); +} +static DEVICE_ATTR_RO(power_state); + static struct attribute *port_hdr_attrs[] = { &dev_attr_id.attr, + &dev_attr_ltr.attr, + &dev_attr_ap1_event.attr, + &dev_attr_ap2_event.attr, + &dev_attr_power_state.attr, NULL, }; ATTRIBUTE_GROUPS(port_hdr); -- cgit v1.2.3