From: Eddie James <eajames@linux.vnet.ibm.com>
To: openbmc@lists.ozlabs.org
Cc: joel@jms.id.au, "Edward A. James" <eajames@us.ibm.com>
Subject: [PATCH linux dev-4.10 v2 2/5] drivers: hwmon: occ: Add new sensor versions and non-hwmon attributes
Date: Fri, 9 Jun 2017 13:01:02 -0500 [thread overview]
Message-ID: <1497031265-29545-3-git-send-email-eajames@linux.vnet.ibm.com> (raw)
In-Reply-To: <1497031265-29545-1-git-send-email-eajames@linux.vnet.ibm.com>
From: "Edward A. James" <eajames@us.ibm.com>
Switch to versioned sensors which can be used for both p8 and p9. This
adds more common code and removes the need for the processor-specific
functions (other than the OCC access code).
Also add non-hwmon attributes for OCC status.
Signed-off-by: Edward A. James <eajames@us.ibm.com>
---
drivers/hwmon/occ/Makefile | 2 +-
drivers/hwmon/occ/common.c | 991 ++++++++++++++++++++++++++++++++++++++++++++-
drivers/hwmon/occ/common.h | 17 +
drivers/hwmon/occ/p9.c | 350 ----------------
drivers/hwmon/occ/p9.h | 17 -
drivers/hwmon/occ/p9_sbe.c | 30 +-
6 files changed, 1020 insertions(+), 387 deletions(-)
delete mode 100644 drivers/hwmon/occ/p9.c
delete mode 100644 drivers/hwmon/occ/p9.h
diff --git a/drivers/hwmon/occ/Makefile b/drivers/hwmon/occ/Makefile
index 3b0ddc6..6245c25 100644
--- a/drivers/hwmon/occ/Makefile
+++ b/drivers/hwmon/occ/Makefile
@@ -1 +1 @@
-obj-y += p9.o p9_sbe.o common.o
+obj-y += p9_sbe.o common.o
diff --git a/drivers/hwmon/occ/common.c b/drivers/hwmon/occ/common.c
index 1f17def..bee64cd 100644
--- a/drivers/hwmon/occ/common.c
+++ b/drivers/hwmon/occ/common.c
@@ -7,8 +7,114 @@
* (at your option) any later version.
*/
+#include <asm/unaligned.h>
#include "common.h"
+#define OCC_NUM_STATUS_ATTRS 6
+
+#define OCC_STAT_ACTIVE 0x01
+#define OCC_EXT_STAT_DVFS_OT 0x80
+#define OCC_EXT_STAT_DVFS_POWER 0x40
+#define OCC_EXT_STAT_MEM_THROTTLE 0x20
+#define OCC_EXT_STAT_QUICK_DROP 0x10
+
+struct temp_sensor_1 {
+ u16 sensor_id;
+ u16 value;
+} __packed;
+
+struct temp_sensor_2 {
+ u32 sensor_id;
+ u8 fru_type;
+ u8 value;
+} __packed;
+
+struct freq_sensor_1 {
+ u16 sensor_id;
+ u16 value;
+} __packed;
+
+struct freq_sensor_2 {
+ u32 sensor_id;
+ u16 value;
+} __packed;
+
+struct power_sensor_1 {
+ u16 sensor_id;
+ u32 update_tag;
+ u32 accumulator;
+ u16 value;
+} __packed;
+
+struct power_sensor_2 {
+ u32 sensor_id;
+ u8 function_id;
+ u8 apss_channel;
+ u16 reserved;
+ u32 update_tag;
+ u64 accumulator;
+ u16 value;
+} __packed;
+
+struct power_sensor_data {
+ u16 value;
+ u32 update_tag;
+ u64 accumulator;
+} __packed;
+
+struct power_sensor_data_and_time {
+ u16 update_time;
+ u16 value;
+ u32 update_tag;
+ u64 accumulator;
+} __packed;
+
+struct power_sensor_a0 {
+ u32 sensor_id;
+ struct power_sensor_data_and_time system;
+ u32 reserved;
+ struct power_sensor_data_and_time proc;
+ struct power_sensor_data vdd;
+ struct power_sensor_data vdn;
+} __packed;
+
+struct caps_sensor_1 {
+ u16 curr_powercap;
+ u16 curr_powerreading;
+ u16 norm_powercap;
+ u16 max_powercap;
+ u16 min_powercap;
+ u16 user_powerlimit;
+} __packed;
+
+struct caps_sensor_2 {
+ u16 curr_powercap;
+ u16 curr_powerreading;
+ u16 norm_powercap;
+ u16 max_powercap;
+ u16 min_powercap;
+ u16 user_powerlimit;
+ u8 user_powerlimit_source;
+} __packed;
+
+struct caps_sensor_3 {
+ u16 curr_powercap;
+ u16 curr_powerreading;
+ u16 norm_powercap;
+ u16 max_powercap;
+ u16 hard_min_powercap;
+ u16 soft_min_powercap;
+ u16 user_powerlimit;
+ u8 user_powerlimit_source;
+} __packed;
+
+struct extended_sensor {
+ u8 name[4];
+ u8 flags;
+ u8 reserved;
+ u8 data[6];
+} __packed;
+
void occ_parse_poll_response(struct occ *occ)
{
unsigned int i, offset = 0, size = 0;
@@ -40,6 +146,8 @@ void occ_parse_poll_response(struct occ *occ)
sensor = &sensors->power;
else if (strncmp(block->header.eye_catcher, "CAPS", 4) == 0)
sensor = &sensors->caps;
+ else if (strncmp(block->header.eye_catcher, "EXTN", 4) == 0)
+ sensor = &sensors->extended;
else {
dev_warn(occ->bus_dev, "sensor not supported %.4s\n",
block->header.eye_catcher);
@@ -47,6 +155,7 @@ void occ_parse_poll_response(struct occ *occ)
}
sensor->num_sensors = block->header.num_sensors;
+ sensor->version = block->header.sensor_format;
sensor->data = &block->data;
}
}
@@ -73,8 +182,9 @@ int occ_set_user_power_cap(struct occ *occ, u16 user_power_cap)
int rc;
u8 cmd[8];
u16 checksum = 0x24;
+ __be16 user_power_cap_be;
- user_power_cap = cpu_to_be16(user_power_cap);
+ user_power_cap_be = cpu_to_be16(user_power_cap);
cmd[0] = 0;
cmd[1] = 0x22;
@@ -108,3 +218,882 @@ int occ_update_response(struct occ *occ)
mutex_unlock(&occ->lock);
return rc;
}
+
+static ssize_t occ_show_status(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int rc;
+ int val;
+ struct occ *occ = dev_get_drvdata(dev);
+ struct occ_poll_response_header *header;
+ struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+
+ rc = occ_update_response(occ);
+ if (rc)
+ return rc;
+
+ header = (struct occ_poll_response_header *)occ->resp.data;
+
+ switch (sattr->index) {
+ case 0:
+ val = header->status & OCC_STAT_ACTIVE;
+ break;
+ case 1:
+ val = header->ext_status & OCC_EXT_STAT_DVFS_OT;
+ break;
+ case 2:
+ val = header->ext_status & OCC_EXT_STAT_DVFS_POWER;
+ break;
+ case 3:
+ val = header->ext_status & OCC_EXT_STAT_MEM_THROTTLE;
+ break;
+ case 4:
+ val = header->ext_status & OCC_EXT_STAT_QUICK_DROP;
+ break;
+ case 5:
+ val = header->occ_state;
+ break;
+ }
+
+ return snprintf(buf, PAGE_SIZE - 1, "%d\n", val);
+}
+
+static ssize_t occ_show_temp_1(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int rc;
+ u16 val = 0;
+ struct temp_sensor_1 *temp;
+ struct occ *occ = dev_get_drvdata(dev);
+ struct occ_sensors *sensors = &occ->sensors;
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ rc = occ_update_response(occ);
+ if (rc)
+ return rc;
+
+ temp = ((struct temp_sensor_1 *)sensors->temp.data) + sattr->index;
+
+ switch (sattr->nr) {
+ case 0:
+ val = get_unaligned_be16(&temp->sensor_id);
+ break;
+ case 1:
+ val = get_unaligned_be16(&temp->value) * 1000;
+ break;
+ }
+
+ return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+}
+
+static ssize_t occ_show_temp_2(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int rc;
+ u32 val = 0;
+ struct temp_sensor_2 *temp;
+ struct occ *occ = dev_get_drvdata(dev);
+ struct occ_sensors *sensors = &occ->sensors;
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ rc = occ_update_response(occ);
+ if (rc)
+ return rc;
+
+ temp = ((struct temp_sensor_2 *)sensors->temp.data) + sattr->index;
+
+ switch (sattr->nr) {
+ case 0:
+ val = get_unaligned_be32(&temp->sensor_id);
+ break;
+ case 1:
+ val = temp->value * 1000;
+ break;
+ case 2:
+ val = temp->fru_type;
+ break;
+ }
+
+ return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+}
+
+static ssize_t occ_show_freq_1(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int rc;
+ u16 val = 0;
+ struct freq_sensor_1 *freq;
+ struct occ *occ = dev_get_drvdata(dev);
+ struct occ_sensors *sensors = &occ->sensors;
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ rc = occ_update_response(occ);
+ if (rc)
+ return rc;
+
+ freq = ((struct freq_sensor_1 *)sensors->freq.data) + sattr->index;
+
+ switch (sattr->nr) {
+ case 0:
+ val = get_unaligned_be16(&freq->sensor_id);
+ break;
+ case 1:
+ val = get_unaligned_be16(&freq->value);
+ break;
+ }
+
+ return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+}
+
+static ssize_t occ_show_freq_2(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int rc;
+ u32 val = 0;
+ struct freq_sensor_2 *freq;
+ struct occ *occ = dev_get_drvdata(dev);
+ struct occ_sensors *sensors = &occ->sensors;
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ rc = occ_update_response(occ);
+ if (rc)
+ return rc;
+
+ freq = ((struct freq_sensor_2 *)sensors->freq.data) + sattr->index;
+
+ switch (sattr->nr) {
+ case 0:
+ val = get_unaligned_be32(&freq->sensor_id);
+ break;
+ case 1:
+ val = get_unaligned_be16(&freq->value);
+ break;
+ }
+
+ return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+}
+
+static ssize_t occ_show_power_1(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int rc;
+ u32 val = 0;
+ struct power_sensor_1 *power;
+ struct occ *occ = dev_get_drvdata(dev);
+ struct occ_sensors *sensors = &occ->sensors;
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ rc = occ_update_response(occ);
+ if (rc)
+ return rc;
+
+ power = ((struct power_sensor_1 *)sensors->power.data) + sattr->index;
+
+ switch (sattr->nr) {
+ case 0:
+ val = get_unaligned_be16(&power->sensor_id);
+ break;
+ case 1:
+ val = get_unaligned_be32(&power->update_tag);
+ break;
+ case 2:
+ val = get_unaligned_be32(&power->accumulator);
+ break;
+ case 3:
+ val = get_unaligned_be16(&power->value);
+ break;
+ }
+
+ return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+}
+
+static ssize_t occ_show_power_2(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int rc;
+ u64 val = 0;
+ struct power_sensor_2 *power;
+ struct occ *occ = dev_get_drvdata(dev);
+ struct occ_sensors *sensors = &occ->sensors;
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ rc = occ_update_response(occ);
+ if (rc)
+ return rc;
+
+ power = ((struct power_sensor_2 *)sensors->power.data) + sattr->index;
+
+ switch (sattr->nr) {
+ case 0:
+ val = get_unaligned_be32(&power->sensor_id);
+ break;
+ case 1:
+ val = get_unaligned_be32(&power->update_tag);
+ break;
+ case 2:
+ val = get_unaligned_be64(&power->accumulator);
+ break;
+ case 3:
+ val = get_unaligned_be16(&power->value);
+ break;
+ case 4:
+ val = power->function_id;
+ break;
+ case 5:
+ val = power->apss_channel;
+ break;
+ }
+
+ return snprintf(buf, PAGE_SIZE - 1, "%llu\n", val);
+}
+
+static ssize_t occ_show_power_a0(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int rc;
+ u64 val = 0;
+ struct power_sensor_a0 *power;
+ struct occ *occ = dev_get_drvdata(dev);
+ struct occ_sensors *sensors = &occ->sensors;
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ rc = occ_update_response(occ);
+ if (rc)
+ return rc;
+
+ power = ((struct power_sensor_a0 *)sensors->power.data) + sattr->index;
+
+ switch (sattr->nr) {
+ case 0:
+ val = get_unaligned_be32(&power->sensor_id);
+ break;
+ case 1:
+ val = get_unaligned_be16(&power->system.update_time);
+ break;
+ case 2:
+ val = get_unaligned_be16(&power->system.value);
+ break;
+ case 3:
+ val = get_unaligned_be32(&power->system.update_tag);
+ break;
+ case 4:
+ val = get_unaligned_be64(&power->system.accumulator);
+ break;
+ case 5:
+ val = get_unaligned_be16(&power->proc.update_time);
+ break;
+ case 6:
+ val = get_unaligned_be16(&power->proc.value);
+ break;
+ case 7:
+ val = get_unaligned_be32(&power->proc.update_tag);
+ break;
+ case 8:
+ val = get_unaligned_be64(&power->proc.accumulator);
+ break;
+ case 9:
+ val = get_unaligned_be16(&power->vdd.value);
+ break;
+ case 10:
+ val = get_unaligned_be32(&power->vdd.update_tag);
+ break;
+ case 11:
+ val = get_unaligned_be64(&power->vdd.accumulator);
+ break;
+ case 12:
+ val = get_unaligned_be16(&power->vdn.value);
+ break;
+ case 13:
+ val = get_unaligned_be32(&power->vdn.update_tag);
+ break;
+ case 14:
+ val = get_unaligned_be64(&power->vdn.accumulator);
+ break;
+ }
+
+ return snprintf(buf, PAGE_SIZE - 1, "%llu\n", val);
+}
+
+
+static ssize_t occ_show_caps_1(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int rc;
+ u16 val = 0;
+ struct caps_sensor_1 *caps;
+ struct occ *occ = dev_get_drvdata(dev);
+ struct occ_sensors *sensors = &occ->sensors;
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ rc = occ_update_response(occ);
+ if (rc)
+ return rc;
+
+ caps = ((struct caps_sensor_1 *)sensors->caps.data) + sattr->index;
+
+ switch (sattr->nr) {
+ case 0:
+ val = get_unaligned_be16(&caps->curr_powercap);
+ break;
+ case 1:
+ val = get_unaligned_be16(&caps->curr_powerreading);
+ break;
+ case 2:
+ val = get_unaligned_be16(&caps->norm_powercap);
+ break;
+ case 3:
+ val = get_unaligned_be16(&caps->max_powercap);
+ break;
+ case 4:
+ val = get_unaligned_be16(&caps->min_powercap);
+ break;
+ case 5:
+ val = get_unaligned_be16(&caps->user_powerlimit);
+ break;
+ }
+
+ return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+}
+
+static ssize_t occ_show_caps_2(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int rc;
+ u16 val = 0;
+ struct caps_sensor_2 *caps;
+ struct occ *occ = dev_get_drvdata(dev);
+ struct occ_sensors *sensors = &occ->sensors;
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ rc = occ_update_response(occ);
+ if (rc)
+ return rc;
+
+ caps = ((struct caps_sensor_2 *)sensors->caps.data) + sattr->index;
+
+ switch (sattr->nr) {
+ case 0:
+ val = get_unaligned_be16(&caps->curr_powercap);
+ break;
+ case 1:
+ val = get_unaligned_be16(&caps->curr_powerreading);
+ break;
+ case 2:
+ val = get_unaligned_be16(&caps->norm_powercap);
+ break;
+ case 3:
+ val = get_unaligned_be16(&caps->max_powercap);
+ break;
+ case 4:
+ val = get_unaligned_be16(&caps->min_powercap);
+ break;
+ case 5:
+ val = get_unaligned_be16(&caps->user_powerlimit);
+ break;
+ case 6:
+ val = caps->user_powerlimit_source;
+ break;
+ }
+
+ return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+}
+
+static ssize_t occ_show_caps_3(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int rc;
+ u16 val = 0;
+ struct caps_sensor_3 *caps;
+ struct occ *occ = dev_get_drvdata(dev);
+ struct occ_sensors *sensors = &occ->sensors;
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ rc = occ_update_response(occ);
+ if (rc)
+ return rc;
+
+ caps = ((struct caps_sensor_3 *)sensors->caps.data) + sattr->index;
+
+ switch (sattr->nr) {
+ case 0:
+ val = get_unaligned_be16(&caps->curr_powercap);
+ break;
+ case 1:
+ val = get_unaligned_be16(&caps->curr_powerreading);
+ break;
+ case 2:
+ val = get_unaligned_be16(&caps->norm_powercap);
+ break;
+ case 3:
+ val = get_unaligned_be16(&caps->max_powercap);
+ break;
+ case 4:
+ val = get_unaligned_be16(&caps->hard_min_powercap);
+ break;
+ case 5:
+ val = get_unaligned_be16(&caps->user_powerlimit);
+ break;
+ case 6:
+ val = caps->user_powerlimit_source;
+ break;
+ case 7:
+ val = get_unaligned_be16(&caps->soft_min_powercap);
+ break;
+ }
+
+ return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
+}
+
+
+static ssize_t occ_store_caps_user(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int rc;
+ u16 user_power_cap;
+ struct occ *occ = dev_get_drvdata(dev);
+
+ rc = kstrtou16(buf, 0, &user_power_cap);
+ if (rc)
+ return rc;
+
+ rc = occ_set_user_power_cap(occ, user_power_cap);
+ if (rc)
+ return rc;
+
+ return count;
+}
+
+static ssize_t occ_show_extended(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int rc;
+ struct extended_sensor *extn;
+ struct occ *occ = dev_get_drvdata(dev);
+ struct occ_sensors *sensors = &occ->sensors;
+ struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+ rc = occ_update_response(occ);
+ if (rc)
+ return rc;
+
+ extn = ((struct extended_sensor *)sensors->extended.data) +
+ sattr->index;
+
+ switch (sattr->nr) {
+ case 0:
+ rc = snprintf(buf, PAGE_SIZE - 1, "%02x%02x%02x%02x\n",
+ extn->name[0], extn->name[1], extn->name[2],
+ extn->name[3]);
+ break;
+ case 1:
+ rc = snprintf(buf, PAGE_SIZE - 1, "%02x\n", extn->flags);
+ break;
+ case 2:
+ rc = snprintf(buf, PAGE_SIZE - 1, "%02x%02x%02x%02x%02x%02x\n",
+ extn->data[0], extn->data[1], extn->data[2],
+ extn->data[3], extn->data[4], extn->data[5]);
+ break;
+ }
+
+ return rc;
+}
+
+int occ_setup_sensor_attrs(struct occ *occ)
+{
+ unsigned int i, s;
+ struct device *dev = occ->bus_dev;
+ struct occ_sensors *sensors = &occ->sensors;
+ struct occ_attribute *attr;
+ ssize_t (*show_temp)(struct device *, struct device_attribute *,
+ char *) = occ_show_temp_1;
+ ssize_t (*show_freq)(struct device *, struct device_attribute *,
+ char *) = occ_show_freq_1;
+ ssize_t (*show_power)(struct device *, struct device_attribute *,
+ char *) = occ_show_power_1;
+ ssize_t (*show_caps)(struct device *, struct device_attribute *,
+ char *) = occ_show_caps_1;
+
+ occ->num_attrs = 0;
+
+ switch (sensors->temp.version) {
+ case 1:
+ occ->num_attrs += (sensors->temp.num_sensors * 2);
+ break;
+ case 2:
+ occ->num_attrs += (sensors->temp.num_sensors * 3);
+ show_temp = occ_show_temp_2;
+ break;
+ default:
+ sensors->temp.num_sensors = 0;
+ }
+
+ switch (sensors->freq.version) {
+ case 2:
+ show_freq = occ_show_freq_2;
+ /* fall through */
+ case 1:
+ occ->num_attrs += (sensors->freq.num_sensors * 2);
+ break;
+ default:
+ sensors->freq.num_sensors = 0;
+ }
+
+ switch (sensors->power.version) {
+ case 1:
+ occ->num_attrs += (sensors->power.num_sensors * 4);
+ break;
+ case 2:
+ occ->num_attrs += (sensors->power.num_sensors * 6);
+ show_power = occ_show_power_2;
+ break;
+ case 0xA0:
+ occ->num_attrs += (sensors->power.num_sensors * 15);
+ show_power = occ_show_power_a0;
+ break;
+ default:
+ sensors->power.num_sensors = 0;
+ }
+
+ switch (sensors->caps.version) {
+ case 1:
+ occ->num_attrs += (sensors->caps.num_sensors * 6);
+ break;
+ case 2:
+ occ->num_attrs += (sensors->caps.num_sensors * 7);
+ show_caps = occ_show_caps_2;
+ break;
+ case 3:
+ occ->num_attrs += (sensors->caps.num_sensors * 8);
+ show_caps = occ_show_caps_3;
+ break;
+ default:
+ sensors->caps.num_sensors = 0;
+ }
+
+ switch (sensors->extended.version) {
+ case 1:
+ occ->num_attrs += sensors->extended.num_sensors;
+ break;
+ default:
+ sensors->extended.num_sensors = 0;
+ }
+
+ occ->attrs = devm_kzalloc(dev, sizeof(*occ->attrs) * occ->num_attrs,
+ GFP_KERNEL);
+ if (!occ->attrs)
+ return -ENOMEM;
+
+ occ->group.attrs = devm_kzalloc(dev, sizeof(*occ->group.attrs) *
+ occ->num_attrs + 1, GFP_KERNEL);
+ if (!occ->group.attrs)
+ return -ENOMEM;
+
+ attr = occ->attrs;
+
+ for (i = 0; i < sensors->temp.num_sensors; ++i) {
+ s = i + 1;
+
+ snprintf(attr->name, sizeof(attr->name), "temp%d_label", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_temp, NULL,
+ 0, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name), "temp%d_input", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_temp, NULL,
+ 1, i);
+ attr++;
+
+ if (sensors->temp.version > 1) {
+ snprintf(attr->name, sizeof(attr->name),
+ "temp%d_fru_type", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_temp, NULL, 2, i);
+ attr++;
+ }
+ }
+
+ for (i = 0; i < sensors->freq.num_sensors; ++i) {
+ s = i + 1;
+
+ snprintf(attr->name, sizeof(attr->name), "freq%d_label", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_freq, NULL,
+ 0, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name), "freq%d_input", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_freq, NULL,
+ 1, i);
+ attr++;
+ }
+
+ if (sensors->power.version == 0xA0) {
+ for (i = 0; i < sensors->power.num_sensors; ++i) {
+ s = i + 1;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_label", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 0, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_system_update_time", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 1, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_system_value", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 2, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_system_update_tag", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 3, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_system_accumulator", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 4, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_proc_update_time", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 5, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_proc_value", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 6, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_proc_update_tag", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 7, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_proc_accumulator", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 8, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_vdd_value", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 9, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_vdd_update_tag", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 10, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_vdd_accumulator", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 11, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_vdn_value", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 12, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_vdn_update_tag", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 13, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_vdn_accumulator", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 14, i);
+ attr++;
+ }
+ } else {
+ for (i = 0; i < sensors->power.num_sensors; ++i) {
+ s = i + 1;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_label", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 0, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_update_tag", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 1, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_accumulator", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 2, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_input", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL, 3, i);
+ attr++;
+
+ if (sensors->power.version > 1) {
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_function_id", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL,
+ 4, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "power%d_apss_channel", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_power, NULL,
+ 5, i);
+ attr++;
+ }
+ }
+ }
+
+ for (i = 0; i < sensors->caps.num_sensors; ++i) {
+ s = i + 1;
+
+ snprintf(attr->name, sizeof(attr->name), "caps%d_current", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
+ 0, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name), "caps%d_reading", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
+ 1, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name), "caps%d_norm", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
+ 2, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name), "caps%d_max", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444, show_caps, NULL,
+ 3, i);
+ attr++;
+
+ if (sensors->caps.version > 2) {
+ snprintf(attr->name, sizeof(attr->name),
+ "caps%d_min_hard", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_caps, NULL, 4, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name),
+ "caps%d_min_soft", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_caps, NULL, 7, i);
+ attr++;
+ } else {
+ snprintf(attr->name, sizeof(attr->name), "caps%d_min",
+ s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_caps, NULL, 4, i);
+ attr++;
+ }
+
+ snprintf(attr->name, sizeof(attr->name), "caps%d_user", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0644, show_caps,
+ occ_store_caps_user, 5, i);
+ attr++;
+
+ if (sensors->caps.version > 1) {
+ snprintf(attr->name, sizeof(attr->name),
+ "caps%d_user_source", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ show_caps, NULL, 6, i);
+ attr++;
+ }
+ }
+
+ for (i = 0; i < sensors->extended.num_sensors; ++i) {
+ s = i + 1;
+
+ snprintf(attr->name, sizeof(attr->name), "extn%d_label", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ occ_show_extended, NULL, 0, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name), "extn%d_flags", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ occ_show_extended, NULL, 1, i);
+ attr++;
+
+ snprintf(attr->name, sizeof(attr->name), "extn%d_value", s);
+ attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
+ occ_show_extended, NULL, 2, i);
+ attr++;
+ }
+
+ /* put the sensors in the group */
+ for (i = 0; i < occ->num_attrs; ++i)
+ occ->group.attrs[i] = &occ->attrs[i].sensor.dev_attr.attr;
+
+ return 0;
+}
+
+int occ_create_status_attrs(struct occ *occ)
+{
+ int rc, i;
+ struct device *dev = occ->bus_dev;
+
+ occ->status_attrs = devm_kzalloc(dev, sizeof(*occ->status_attrs) *
+ OCC_NUM_STATUS_ATTRS, GFP_KERNEL);
+ if (!occ->status_attrs)
+ return -ENOMEM;
+
+ occ->status_attrs[0] =
+ (struct sensor_device_attribute)SENSOR_ATTR(occ_active, 0444,
+ occ_show_status,
+ NULL, 0);
+ occ->status_attrs[1] =
+ (struct sensor_device_attribute)SENSOR_ATTR(occ_dvfs_ot, 0444,
+ occ_show_status,
+ NULL, 1);
+ occ->status_attrs[2] =
+ (struct sensor_device_attribute)SENSOR_ATTR(occ_dvfs_power,
+ 0444,
+ occ_show_status,
+ NULL, 2);
+ occ->status_attrs[3] =
+ (struct sensor_device_attribute)SENSOR_ATTR(occ_mem_throttle,
+ 0444,
+ occ_show_status,
+ NULL, 3);
+ occ->status_attrs[4] =
+ (struct sensor_device_attribute)SENSOR_ATTR(occ_quick_drop,
+ 0444,
+ occ_show_status,
+ NULL, 4);
+ occ->status_attrs[5] =
+ (struct sensor_device_attribute)SENSOR_ATTR(occ_status, 0444,
+ occ_show_status,
+ NULL, 5);
+
+ for (i = 0; i < OCC_NUM_STATUS_ATTRS; ++i) {
+ rc = device_create_file(dev, &occ->status_attrs[i].dev_attr);
+ if (rc)
+ dev_warn(dev, "error %d creating status attr %d\n", rc,
+ i);
+ }
+
+ return 0;
+}
diff --git a/drivers/hwmon/occ/common.h b/drivers/hwmon/occ/common.h
index a3d733a..ad21538 100644
--- a/drivers/hwmon/occ/common.h
+++ b/drivers/hwmon/occ/common.h
@@ -16,6 +16,18 @@
#define OCC_UPDATE_FREQUENCY msecs_to_jiffies(1000)
#define OCC_RESP_DATA_BYTES 4089
+#define OCC_TIMEOUT_MS 5000
+#define OCC_CMD_IN_PRG_MS 100
+
+#define RESP_RETURN_CMD_IN_PRG 0xFF
+#define RESP_RETURN_SUCCESS 0
+#define RESP_RETURN_CMD_INVAL 0x11
+#define RESP_RETURN_CMD_LEN 0x12
+#define RESP_RETURN_DATA_INVAL 0x13
+#define RESP_RETURN_CHKSUM 0x14
+#define RESP_RETURN_OCC_ERR 0x15
+#define RESP_RETURN_STATE 0x16
+
struct occ_response {
u8 seq_no;
u8 cmd_type;
@@ -63,6 +75,7 @@ struct occ_poll_response {
struct occ_sensor {
u8 num_sensors;
+ u8 version;
void *data;
};
@@ -71,6 +84,7 @@ struct occ_sensors {
struct occ_sensor freq;
struct occ_sensor power;
struct occ_sensor caps;
+ struct occ_sensor extended;
};
struct occ_attribute {
@@ -92,6 +106,7 @@ struct occ {
struct occ_attribute *attrs;
struct attribute_group group;
const struct attribute_group *groups[2];
+ struct sensor_device_attribute *status_attrs;
u8 poll_cmd_data;
int (*send_cmd)(struct occ *occ, u8 *cmd);
@@ -120,5 +135,7 @@ struct occ {
int occ_poll(struct occ *occ);
int occ_set_user_power_cap(struct occ *occ, u16 user_power_cap);
int occ_update_response(struct occ *occ);
+int occ_setup_sensor_attrs(struct occ *occ);
+int occ_create_status_attrs(struct occ *occ);
#endif /* __OCC_COMMON_H__ */
diff --git a/drivers/hwmon/occ/p9.c b/drivers/hwmon/occ/p9.c
deleted file mode 100644
index 832d6ff..0000000
--- a/drivers/hwmon/occ/p9.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * Copyright 2017 IBM Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <asm/unaligned.h>
-#include "common.h"
-
-struct p9_temp_sensor {
- u32 sensor_id;
- u8 fru_type;
- u8 value;
-} __packed;
-
-struct p9_freq_sensor {
- u32 sensor_id;
- u16 value;
-} __packed;
-
-struct p9_power_sensor {
- u32 sensor_id;
- u8 function_id;
- u8 apss_channel;
- u16 reserved;
- u32 update_tag;
- u64 accumulator;
- u16 value;
-} __packed;
-
-struct p9_caps_sensor {
- u16 curr_powercap;
- u16 curr_powerreading;
- u16 norm_powercap;
- u16 max_powercap;
- u16 min_powercap;
- u16 user_powerlimit;
- u8 user_powerlimit_source;
-} __packed;
-
-static ssize_t p9_occ_show_temp(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int rc;
- u32 val = 0;
- struct p9_temp_sensor *temp;
- struct occ *occ = dev_get_drvdata(dev);
- struct occ_sensors *sensors = &occ->sensors;
- struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
-
- rc = occ_update_response(occ);
- if (rc)
- return rc;
-
- temp = ((struct p9_temp_sensor *)sensors->temp.data) + sattr->index;
-
- switch (sattr->nr) {
- case 0:
- val = be32_to_cpu(get_unaligned(&temp->sensor_id));
- break;
- case 1:
- val = temp->fru_type;
- break;
- case 2:
- /* millidegree */
- val = temp->value * 1000;
- break;
- }
-
- return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
-}
-
-static ssize_t p9_occ_show_freq(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int rc;
- u32 val = 0;
- struct p9_freq_sensor *freq;
- struct occ *occ = dev_get_drvdata(dev);
- struct occ_sensors *sensors = &occ->sensors;
- struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
-
- rc = occ_update_response(occ);
- if (rc)
- return rc;
-
- freq = ((struct p9_freq_sensor *)sensors->freq.data) + sattr->index;
-
- switch (sattr->nr) {
- case 0:
- val = be32_to_cpu(get_unaligned(&freq->sensor_id));
- break;
- case 1:
- val = be16_to_cpu(get_unaligned(&freq->value));
- break;
- }
-
- return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
-}
-
-static ssize_t p9_occ_show_power(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int rc;
- u64 val = 0;
- struct p9_power_sensor *power;
- struct occ *occ = dev_get_drvdata(dev);
- struct occ_sensors *sensors = &occ->sensors;
- struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
-
- rc = occ_update_response(occ);
- if (rc)
- return rc;
-
- power = ((struct p9_power_sensor *)sensors->power.data) + sattr->index;
-
- switch (sattr->nr) {
- case 0:
- val = be32_to_cpu(get_unaligned(&power->sensor_id));
- break;
- case 1:
- val = power->function_id;
- break;
- case 2:
- val = power->apss_channel;
- break;
- case 3:
- val = be32_to_cpu(get_unaligned(&power->update_tag));
- break;
- case 4:
- val = be64_to_cpu(get_unaligned(&power->accumulator));
- break;
- case 5:
- val = be16_to_cpu(get_unaligned(&power->value));
- break;
- }
-
- return snprintf(buf, PAGE_SIZE - 1, "%llu\n", val);
-}
-
-static ssize_t p9_occ_show_caps(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- int rc;
- u16 val = 0;
- struct p9_caps_sensor *caps;
- struct occ *occ = dev_get_drvdata(dev);
- struct occ_sensors *sensors = &occ->sensors;
- struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
-
- rc = occ_update_response(occ);
- if (rc)
- return rc;
-
- caps = ((struct p9_caps_sensor *)sensors->caps.data) + sattr->index;
-
- switch (sattr->nr) {
- case 0:
- val = be16_to_cpu(get_unaligned(&caps->curr_powercap));
- break;
- case 1:
- val = be16_to_cpu(get_unaligned(&caps->curr_powerreading));
- break;
- case 2:
- val = be16_to_cpu(get_unaligned(&caps->norm_powercap));
- break;
- case 3:
- val = be16_to_cpu(get_unaligned(&caps->max_powercap));
- break;
- case 4:
- val = be16_to_cpu(get_unaligned(&caps->min_powercap));
- break;
- case 5:
- val = be16_to_cpu(get_unaligned(&caps->user_powerlimit));
- break;
- case 6:
- val = caps->user_powerlimit_source;
- break;
- }
-
- return snprintf(buf, PAGE_SIZE - 1, "%u\n", val);
-}
-
-static ssize_t p9_occ_store_caps_user(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int rc;
- u16 user_power_cap;
- struct occ *occ = dev_get_drvdata(dev);
-
- rc = kstrtou16(buf, 0, &user_power_cap);
- if (rc)
- return rc;
-
- rc = occ_set_user_power_cap(occ, user_power_cap);
- if (rc)
- return rc;
-
- return count;
-}
-
-int p9_occ_setup_sensor_attrs(struct occ *occ)
-{
- unsigned int i, s;
- struct device *dev = occ->bus_dev;
- struct occ_sensors *sensors = &occ->sensors;
- struct occ_attribute *attr;
-
- occ->num_attrs = (sensors->temp.num_sensors * 3);
- occ->num_attrs += (sensors->freq.num_sensors * 2);
- occ->num_attrs += (sensors->power.num_sensors * 6);
- occ->num_attrs += (sensors->caps.num_sensors * 7);
-
- occ->attrs = devm_kzalloc(dev, sizeof(*occ->attrs) * occ->num_attrs,
- GFP_KERNEL);
- if (!occ->attrs)
- return -ENOMEM;
-
- occ->group.attrs = devm_kzalloc(dev, sizeof(*occ->group.attrs) *
- occ->num_attrs + 1, GFP_KERNEL);
- if (!occ->group.attrs)
- return -ENOMEM;
-
- attr = occ->attrs;
- for (i = 0; i < sensors->temp.num_sensors; ++i) {
- s = i + 1;
-
- snprintf(attr->name, sizeof(attr->name), "temp%d_label", s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_temp, NULL, 0, i);
- attr++;
-
- snprintf(attr->name, sizeof(attr->name), "temp%d_fru_type", s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_temp, NULL, 1, i);
- attr++;
-
- snprintf(attr->name, sizeof(attr->name), "temp%d_input", s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_temp, NULL, 2, i);
- attr++;
- }
-
- for (i = 0; i < sensors->freq.num_sensors; ++i) {
- s = i + 1;
-
- snprintf(attr->name, sizeof(attr->name), "freq%d_label", s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_freq, NULL, 0, i);
- attr++;
-
- snprintf(attr->name, sizeof(attr->name), "freq%d_input", s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_freq, NULL, 1, i);
- attr++;
- }
-
- for (i = 0; i < sensors->power.num_sensors; ++i) {
- s = i + 1;
-
- snprintf(attr->name, sizeof(attr->name), "power%d_label", s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_power, NULL, 0, i);
- attr++;
-
- snprintf(attr->name, sizeof(attr->name), "power%d_function_id",
- s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_power, NULL, 1, i);
- attr++;
-
- snprintf(attr->name, sizeof(attr->name),
- "power%d_apss_channel", s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_power, NULL, 2, i);
- attr++;
-
- snprintf(attr->name, sizeof(attr->name), "power%d_update_tag",
- s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_power, NULL, 3, i);
- attr++;
-
- snprintf(attr->name, sizeof(attr->name), "power%d_accumulator",
- s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_power, NULL, 4, i);
- attr++;
-
- snprintf(attr->name, sizeof(attr->name), "power%d_input", s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_power, NULL, 5, i);
- attr++;
- }
-
- for (i = 0; i < sensors->caps.num_sensors; ++i) {
- s = i + 1;
-
- snprintf(attr->name, sizeof(attr->name), "caps%d_curr", s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_caps, NULL, 0, i);
- attr++;
-
- snprintf(attr->name, sizeof(attr->name), "caps%d_reading", s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_caps, NULL, 1, i);
- attr++;
-
- snprintf(attr->name, sizeof(attr->name), "caps%d_norm", s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_caps, NULL, 2, i);
- attr++;
-
- snprintf(attr->name, sizeof(attr->name), "caps%d_max", s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_caps, NULL, 3, i);
- attr++;
-
- snprintf(attr->name, sizeof(attr->name), "caps%d_min", s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_caps, NULL, 4, i);
- attr++;
-
- snprintf(attr->name, sizeof(attr->name), "caps%d_user", s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0644,
- p9_occ_show_caps,
- p9_occ_store_caps_user, 5, i);
- attr++;
-
- snprintf(attr->name, sizeof(attr->name), "caps%d_user_source",
- s);
- attr->sensor = OCC_INIT_ATTR(attr->name, 0444,
- p9_occ_show_caps, NULL, 6, i);
- attr++;
- }
-
- /* put the sensors in the group */
- for (i = 0; i < occ->num_attrs; ++i)
- occ->group.attrs[i] = &occ->attrs[i].sensor.dev_attr.attr;
-
- return 0;
-}
diff --git a/drivers/hwmon/occ/p9.h b/drivers/hwmon/occ/p9.h
deleted file mode 100644
index 12d1bc5..0000000
--- a/drivers/hwmon/occ/p9.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * Copyright 2017 IBM Corp.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __OCC_P9_H__
-#define __OCC_P9_H__
-
-struct occ;
-
-int p9_occ_setup_sensor_attrs(struct occ *occ);
-
-#endif /* __OCC_P9_H__ */
diff --git a/drivers/hwmon/occ/p9_sbe.c b/drivers/hwmon/occ/p9_sbe.c
index 88f71b1..fe435ef 100644
--- a/drivers/hwmon/occ/p9_sbe.c
+++ b/drivers/hwmon/occ/p9_sbe.c
@@ -15,21 +15,8 @@
#include <linux/occ.h>
#include <linux/sched.h>
#include <linux/workqueue.h>
-#include "p9.h"
-#define P9_SBE_OCC_SETUP_DELAY 2500
-
-#define OCC_TIMEOUT_MS 5000
-#define OCC_CMD_IN_PRG_MS 100
-
-#define RESP_RETURN_CMD_IN_PRG 0xFF
-#define RESP_RETURN_SUCCESS 0
-#define RESP_RETURN_CMD_INVAL 0x11
-#define RESP_RETURN_CMD_LEN 0x12
-#define RESP_RETURN_DATA_INVAL 0x13
-#define RESP_RETURN_CHKSUM 0x14
-#define RESP_RETURN_OCC_ERR 0x15
-#define RESP_RETURN_STATE 0x16
+#define P9_SBE_OCC_SETUP_DELAY 5000
struct p9_sbe_occ {
struct occ occ;
@@ -66,7 +53,8 @@ static int p9_sbe_occ_send_cmd(struct occ *occ, u8 *cmd)
switch (resp->return_status) {
case RESP_RETURN_CMD_IN_PRG:
- if (time_after(jiffies, start + msecs_to_jiffies(OCC_TIMEOUT_MS)))
+ if (time_after(jiffies,
+ start + msecs_to_jiffies(OCC_TIMEOUT_MS)))
rc = -EALREADY;
else {
set_current_state(TASK_INTERRUPTIBLE);
@@ -123,7 +111,7 @@ static void p9_sbe_occ_setup(struct work_struct *work)
occ_parse_poll_response(occ);
- rc = p9_occ_setup_sensor_attrs(occ);
+ rc = occ_setup_sensor_attrs(occ);
if (rc) {
dev_err(occ->bus_dev, "failed to setup p9 attrs: %d\n", rc);
return;
@@ -137,6 +125,10 @@ static void p9_sbe_occ_setup(struct work_struct *work)
PTR_ERR(occ->hwmon));
return;
}
+
+ rc = occ_create_status_attrs(occ);
+ if (rc)
+ dev_err(occ->bus_dev, "failed to setup p9 status attrs: %d\n", rc);
}
static int p9_sbe_occ_probe(struct platform_device *pdev)
@@ -157,7 +149,8 @@ static int p9_sbe_occ_probe(struct platform_device *pdev)
occ->send_cmd = p9_sbe_occ_send_cmd;
mutex_init(&occ->lock);
INIT_DELAYED_WORK(&p9_sbe_occ->setup, p9_sbe_occ_setup);
- platform_set_drvdata(pdev, p9_sbe_occ);
+
+ platform_set_drvdata(pdev, occ);
schedule_delayed_work(&p9_sbe_occ->setup,
msecs_to_jiffies(P9_SBE_OCC_SETUP_DELAY));
@@ -167,7 +160,8 @@ static int p9_sbe_occ_probe(struct platform_device *pdev)
static int p9_sbe_occ_remove(struct platform_device *pdev)
{
- struct p9_sbe_occ *p9_sbe_occ = platform_get_drvdata(pdev);
+ struct occ *occ = platform_get_drvdata(pdev);
+ struct p9_sbe_occ *p9_sbe_occ = to_p9_sbe_occ(occ);
cancel_delayed_work_sync(&p9_sbe_occ->setup);
--
1.8.3.1
next prev parent reply other threads:[~2017-06-09 18:01 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-06-09 18:01 [PATCH linux dev-4.10 v2 0/5] drivers: OCC: Update sensors, fix probing, add P8 Eddie James
2017-06-09 18:01 ` [PATCH linux dev-4.10 v2 1/5] drivers: fsi: occ: Fix 1 byte response and rc for O_NONBLOCK Eddie James
2017-06-16 5:11 ` Joel Stanley
2017-06-09 18:01 ` Eddie James [this message]
2017-06-16 5:36 ` [PATCH linux dev-4.10 v2 2/5] drivers: hwmon: occ: Add new sensor versions and non-hwmon attributes Joel Stanley
2017-06-09 18:01 ` [PATCH linux dev-4.10 v2 3/5] drivers: hwmon: occ: Add P8 OCC access Eddie James
2017-06-09 18:01 ` [PATCH linux dev-4.10 v2 4/5] drivers: occ: hwmon and fsi probing fix Eddie James
2017-06-09 18:01 ` [PATCH linux dev-4.10 v2 5/5] aspeed: update power9 dts and defconfigs for OCC Eddie James
2017-06-16 5:40 ` [PATCH linux dev-4.10 v2 0/5] drivers: OCC: Update sensors, fix probing, add P8 Joel Stanley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1497031265-29545-3-git-send-email-eajames@linux.vnet.ibm.com \
--to=eajames@linux.vnet.ibm.com \
--cc=eajames@us.ibm.com \
--cc=joel@jms.id.au \
--cc=openbmc@lists.ozlabs.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.