From patchwork Tue Mar 14 20:55:05 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eddie James X-Patchwork-Id: 9624483 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8706C604CC for ; Tue, 14 Mar 2017 20:55:59 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 78507285D5 for ; Tue, 14 Mar 2017 20:55:59 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6C394285DC; Tue, 14 Mar 2017 20:55:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B2DCB285D5 for ; Tue, 14 Mar 2017 20:55:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753301AbdCNUzo (ORCPT ); Tue, 14 Mar 2017 16:55:44 -0400 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:38275 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753296AbdCNUzj (ORCPT ); Tue, 14 Mar 2017 16:55:39 -0400 Received: from pps.filterd (m0098393.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.20/8.16.0.20) with SMTP id v2EKraDD045971 for ; Tue, 14 Mar 2017 16:55:28 -0400 Received: from e14.ny.us.ibm.com (e14.ny.us.ibm.com [129.33.205.204]) by mx0a-001b2d01.pphosted.com with ESMTP id 296nfvpsf9-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Tue, 14 Mar 2017 16:55:28 -0400 Received: from localhost by e14.ny.us.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Tue, 14 Mar 2017 16:55:27 -0400 Received: from b03cxnp08026.gho.boulder.ibm.com (9.17.130.18) by e14.ny.us.ibm.com (146.89.104.201) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Tue, 14 Mar 2017 16:55:22 -0400 Received: from b03ledav002.gho.boulder.ibm.com (b03ledav002.gho.boulder.ibm.com [9.17.130.233]) by b03cxnp08026.gho.boulder.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v2EKtLEF10420574; Tue, 14 Mar 2017 13:55:21 -0700 Received: from b03ledav002.gho.boulder.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A665613603C; Tue, 14 Mar 2017 14:55:21 -0600 (MDT) Received: from oc3016140333.ibm.com (unknown [9.41.179.225]) by b03ledav002.gho.boulder.ibm.com (Postfix) with ESMTP id D0F16136044; Tue, 14 Mar 2017 14:55:20 -0600 (MDT) From: Eddie James To: linux@roeck-us.net Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, linux-doc@vger.kernel.org, jdelvare@suse.com, corbet@lwn.net, mark.rutland@arm.com, robh+dt@kernel.org, wsa@the-dreams.de, andrew@aj.id.au, benh@kernel.crashing.org, joel@jms.id.au, "Edward A. James" Subject: [PATCH linux v9 4/5] hwmon: occ: Add callbacks for parsing P8 OCC datastructures Date: Tue, 14 Mar 2017 15:55:05 -0500 X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1489524906-19411-1-git-send-email-eajames@linux.vnet.ibm.com> References: <1489524906-19411-1-git-send-email-eajames@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 17031420-0052-0000-0000-000001A1EF1B X-IBM-SpamModules-Scores: X-IBM-SpamModules-Versions: BY=3.00006782; HX=3.00000240; KW=3.00000007; PH=3.00000004; SC=3.00000206; SDB=6.00833846; UDB=6.00409430; IPR=6.00611504; BA=6.00005210; NDR=6.00000001; ZLA=6.00000005; ZF=6.00000009; ZB=6.00000000; ZP=6.00000000; ZH=6.00000000; ZU=6.00000002; MB=3.00014648; XFM=3.00000013; UTC=2017-03-14 20:55:25 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17031420-0053-0000-0000-00004F1F2035 Message-Id: <1489524906-19411-5-git-send-email-eajames@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-03-14_11:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=15 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1702020001 definitions=main-1703140160 Sender: linux-hwmon-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-hwmon@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: "Edward A. James" Add functions to parse the data structures that are specific to the OCC on the POWER8 processor. These are the sensor data structures, including temperature, frequency, power, and "caps." Signed-off-by: Edward A. James Signed-off-by: Andrew Jeffery --- Documentation/hwmon/occ | 9 ++ drivers/hwmon/occ/Makefile | 2 +- drivers/hwmon/occ/occ_p8.c | 256 +++++++++++++++++++++++++++++++++++++++++++++ drivers/hwmon/occ/occ_p8.h | 25 +++++ 4 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 drivers/hwmon/occ/occ_p8.c create mode 100644 drivers/hwmon/occ/occ_p8.h diff --git a/Documentation/hwmon/occ b/Documentation/hwmon/occ index 580af26..4ec8842 100644 --- a/Documentation/hwmon/occ +++ b/Documentation/hwmon/occ @@ -27,6 +27,15 @@ Currently, all versions of the OCC support four types of sensor data: power, temperature, frequency, and "caps," which indicate limits and thresholds used internally on the OCC. +The format for the POWER8 OCC sensor data can be found in the P8 OCC +specification: +github.com/open-power/docs/blob/master/occ/OCC_OpenPwr_FW_Interfaces.pdf +This document provides the details of the OCC sensors: power, frequency, +temperature, and caps. These sensor formats are specific to the POWER8 OCC. A +number of data structures, such as command format, response headers, and the +like, are also defined in this specification, and are common to both POWER8 and +POWER9 OCCs. + sysfs Entries ------------- diff --git a/drivers/hwmon/occ/Makefile b/drivers/hwmon/occ/Makefile index 9cc36e7..f59cca4 100644 --- a/drivers/hwmon/occ/Makefile +++ b/drivers/hwmon/occ/Makefile @@ -1 +1 @@ -obj-$(CONFIG_SENSORS_IBM_OCC) += occ.o occ_sysfs.o occ_scom_i2c.o +obj-$(CONFIG_SENSORS_IBM_OCC) += occ.o occ_sysfs.o occ_scom_i2c.o occ_p8.o diff --git a/drivers/hwmon/occ/occ_p8.c b/drivers/hwmon/occ/occ_p8.c new file mode 100644 index 0000000..ae8b453 --- /dev/null +++ b/drivers/hwmon/occ/occ_p8.c @@ -0,0 +1,256 @@ +/* + * occ_p8.c - OCC hwmon driver + * + * This file contains the Power8-specific methods and data structures for + * the OCC hwmon driver. + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "occ.h" +#include "occ_p8.h" + +/* P8 OCC sensor data format */ +struct p8_occ_sensor { + u16 sensor_id; + u16 value; +}; + +struct p8_power_sensor { + u16 sensor_id; + u32 update_tag; + u32 accumulator; + u16 value; +}; + +struct p8_caps_sensor { + u16 curr_powercap; + u16 curr_powerreading; + u16 norm_powercap; + u16 max_powercap; + u16 min_powercap; + u16 user_powerlimit; +}; + +/* value, sensor_id */ +#define FREQ_SENSOR_CONFIG (HWMON_I_INPUT | HWMON_I_LABEL) +#define TEMP_SENSOR_CONFIG (HWMON_T_INPUT | HWMON_T_LABEL) + +/* value, sensor_id, accumulator, update_tag */ +#define POWER_SENSOR_CONFIG \ +( \ + HWMON_P_INPUT | HWMON_P_LABEL | HWMON_P_AVERAGE | \ + HWMON_P_AVERAGE_INTERVAL \ +) + +/* curr_powercap, max_powercap, min_powercap, norm_powercap, user_powerlimit */ +#define CAPS_SENSOR_CONFIG \ +( \ + HWMON_P_CAP | HWMON_P_CAP_MAX | HWMON_P_CAP_MIN | HWMON_P_MAX | \ + HWMON_P_ALARM \ +) + +static const u32 p8_sensor_hwmon_configs[MAX_OCC_SENSOR_TYPE] = { + FREQ_SENSOR_CONFIG, + TEMP_SENSOR_CONFIG, + POWER_SENSOR_CONFIG, + CAPS_SENSOR_CONFIG, +}; + +void p8_parse_sensor(u8 *data, void *sensor, int sensor_type, int off, + int snum) +{ + switch (sensor_type) { + case FREQ: + case TEMP: + { + struct p8_occ_sensor *os = + &(((struct p8_occ_sensor *)sensor)[snum]); + + os->sensor_id = be16_to_cpu(get_unaligned((u16 *)&data[off])); + os->value = be16_to_cpu(get_unaligned((u16 *)&data[off + 2])); + } + break; + case POWER: + { + struct p8_power_sensor *ps = + &(((struct p8_power_sensor *)sensor)[snum]); + + ps->sensor_id = be16_to_cpu(get_unaligned((u16 *)&data[off])); + ps->update_tag = + be32_to_cpu(get_unaligned((u32 *)&data[off + 2])); + ps->accumulator = + be32_to_cpu(get_unaligned((u32 *)&data[off + 6])); + ps->value = be16_to_cpu(get_unaligned((u16 *)&data[off + 10])); + } + break; + case CAPS: + { + struct p8_caps_sensor *cs = + &(((struct p8_caps_sensor *)sensor)[snum]); + + cs->curr_powercap = + be16_to_cpu(get_unaligned((u16 *)&data[off])); + cs->curr_powerreading = + be16_to_cpu(get_unaligned((u16 *)&data[off + 2])); + cs->norm_powercap = + be16_to_cpu(get_unaligned((u16 *)&data[off + 4])); + cs->max_powercap = + be16_to_cpu(get_unaligned((u16 *)&data[off + 6])); + cs->min_powercap = + be16_to_cpu(get_unaligned((u16 *)&data[off + 8])); + cs->user_powerlimit = + be16_to_cpu(get_unaligned((u16 *)&data[off + 10])); + } + break; + }; +} + +void *p8_alloc_sensor(struct device *dev, int sensor_type, int num_sensors) +{ + switch (sensor_type) { + case FREQ: + case TEMP: + return devm_kzalloc(dev, num_sensors * + sizeof(struct p8_occ_sensor), GFP_KERNEL); + case POWER: + return devm_kzalloc(dev, num_sensors * + sizeof(struct p8_power_sensor), + GFP_KERNEL); + case CAPS: + return devm_kzalloc(dev, num_sensors * + sizeof(struct p8_caps_sensor), GFP_KERNEL); + default: + return NULL; + } +} + +int p8_get_sensor(struct occ *driver, int sensor_type, int sensor_num, + u32 hwmon, long *val) +{ + int rc = 0; + void *sensor; + + if (sensor_type == POWER) { + if (hwmon == hwmon_power_cap || hwmon == hwmon_power_cap_max || + hwmon == hwmon_power_cap_min || hwmon == hwmon_power_max || + hwmon == hwmon_power_alarm) + sensor_type = CAPS; + } + + sensor = occ_get_sensor(driver, sensor_type); + if (!sensor) + return -ENODEV; + + switch (sensor_type) { + case FREQ: + case TEMP: + { + struct p8_occ_sensor *os = + &(((struct p8_occ_sensor *)sensor)[sensor_num]); + + if (hwmon == hwmon_in_input || hwmon == hwmon_temp_input) + *val = os->value; + else if (hwmon == hwmon_in_label || hwmon == hwmon_temp_label) + *val = os->sensor_id; + else + rc = -EOPNOTSUPP; + } + break; + case POWER: + { + struct p8_power_sensor *ps = + &(((struct p8_power_sensor *)sensor)[sensor_num]); + + switch (hwmon) { + case hwmon_power_input: + *val = ps->value; + break; + case hwmon_power_label: + *val = ps->sensor_id; + break; + case hwmon_power_average: + *val = ps->accumulator; + break; + case hwmon_power_average_interval: + *val = ps->update_tag; + break; + default: + rc = -EOPNOTSUPP; + } + } + break; + case CAPS: + { + struct p8_caps_sensor *cs = + &(((struct p8_caps_sensor *)sensor)[sensor_num]); + + switch (hwmon) { + case hwmon_power_cap: + *val = cs->curr_powercap; + break; + case hwmon_power_cap_max: + *val = cs->max_powercap; + break; + case hwmon_power_cap_min: + *val = cs->min_powercap; + break; + case hwmon_power_max: + *val = cs->norm_powercap; + break; + case hwmon_power_alarm: + *val = cs->user_powerlimit; + break; + default: + rc = -EOPNOTSUPP; + } + } + break; + default: + rc = -EINVAL; + } + + return rc; +} + +static const struct occ_ops p8_ops = { + .parse_sensor = p8_parse_sensor, + .alloc_sensor = p8_alloc_sensor, + .get_sensor = p8_get_sensor, +}; + +static const struct occ_init_data p8_init = { + .command_addr = 0xFFFF6000, + .response_addr = 0xFFFF7000, + .ops = &p8_ops, +}; + +const u32 *p8_get_sensor_hwmon_configs() +{ + return p8_sensor_hwmon_configs; +} + +struct occ *p8_occ_init(struct device *dev, void *bus, + const struct occ_bus_ops *bus_ops) +{ + return occ_init(dev, bus, bus_ops, &p8_init); +} + +MODULE_AUTHOR("Eddie James "); +MODULE_DESCRIPTION("P8 OCC sensors"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/occ/occ_p8.h b/drivers/hwmon/occ/occ_p8.h new file mode 100644 index 0000000..5f9cceb --- /dev/null +++ b/drivers/hwmon/occ/occ_p8.h @@ -0,0 +1,25 @@ +/* + * occ_p8.h - OCC hwmon driver + * + * This file contains Power8-specific function prototypes + * + * 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_P8_H__ +#define __OCC_P8_H__ + +struct device; +struct occ; +struct occ_bus_ops; + +const u32 *p8_get_sensor_hwmon_configs(void); +struct occ *p8_occ_init(struct device *dev, void *bus, + const struct occ_bus_ops *bus_ops); + +#endif /* __OCC_P8_H__ */