From patchwork Sat Jun 8 08:12:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Patchwork-Id: 13690846 Received: from todd.t-8ch.de (todd.t-8ch.de [159.69.126.157]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 72DD1176AB4; Sat, 8 Jun 2024 08:12:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.69.126.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717834372; cv=none; b=FyCtJdfdbEzLqS4GJaBEgCf6V5wQWqjOgLK89vMacbIE8ch3dZSpY27SMUmahlTpLx/DvZ6FtNhqijoqnLqEJNsW/dlIFc8Yd5X3LzXFTA88nFJXaQArPqKEDoiB1bP7etZWfjx/3L2DFk1g21zg3D297aUmORir4DkYCR81LRM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717834372; c=relaxed/simple; bh=fw/y4pJzNvdZK5afG+PBEc6PoUftleG4LWfjkyyWgdE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=A2QkdPbwIRz6sEaHkddhNUCaAVCdf/Esue+aMckgU2EP4Z/VBr1KsCnwryiuCeHqkvl9ySNDb0xhyKn5B0L4VHnJm+7nri6IgtLRNKmwOWPLX/ryTiLsDhepBP49awog+dlquPHi1rU3GKtd68urNlcttR/eZDxGanoHqqU5Arw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net; spf=pass smtp.mailfrom=weissschuh.net; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b=hDGxVpzr; arc=none smtp.client-ip=159.69.126.157 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b="hDGxVpzr" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=weissschuh.net; s=mail; t=1717834365; bh=fw/y4pJzNvdZK5afG+PBEc6PoUftleG4LWfjkyyWgdE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=hDGxVpzr4v6gAQwt4+MQ66E5eH90CFQbiNBcikb+fdfVzDvTZkLnreacjF7gg8eYu o4U5QADxXE1ci2VR0FtORdU5J4uMGh0gopS0D/JJN2gtNJFA3ba+9jLXKcnXUoqoTg kWnTz4N/sBiMPE1DZdSIEVV4UE+ZN2X3AmNRW/mk= From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= Date: Sat, 08 Jun 2024 10:12:43 +0200 Subject: [PATCH 1/5] platform/chrome: cros_ec_proto: Introduce cros_ec_cmd_versions() Precedence: bulk X-Mailing-List: linux-hwmon@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240608-cros_ec-hwmon-pwm-v1-1-d29dfc26fbc3@weissschuh.net> References: <20240608-cros_ec-hwmon-pwm-v1-0-d29dfc26fbc3@weissschuh.net> In-Reply-To: <20240608-cros_ec-hwmon-pwm-v1-0-d29dfc26fbc3@weissschuh.net> To: Benson Leung , Tzung-Bi Shih , Guenter Roeck , =?utf-8?q?Thomas_Wei=C3=9Fschuh?= , Jean Delvare , Guenter Roeck Cc: Dustin Howett , Mario Limonciello , Stephen Horvath , chrome-platform@lists.linux.dev, linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, =?utf-8?q?Thoma?= =?utf-8?q?s_Wei=C3=9Fschuh?= X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1717834364; l=2290; i=linux@weissschuh.net; s=20221212; h=from:subject:message-id; bh=fw/y4pJzNvdZK5afG+PBEc6PoUftleG4LWfjkyyWgdE=; b=Dapg4fmR1zg9VbRdnm6FMME0ObVhZaPf2rel7zyHMY2xz8MFj6Pzop/fpuX0q7arf5JIWX+7O Pu80aZ3RhZ9C809lKbIP9LCgv98GdKy2n8nHnVG6wiYFCByb5VpWuMZ X-Developer-Key: i=linux@weissschuh.net; a=ed25519; pk=KcycQgFPX2wGR5azS7RhpBqedglOZVgRPfdFSPB1LNw= Retrieving the supported versions of a command is a fairly common operation. Provide a helper for it. If the command is not supported at all the EC returns -EINVAL/EC_RES_INVALID_PARAMS. This error is translated into an empty version mask as that is easier to handle for callers and they don't need to know about the error details. Signed-off-by: Thomas Weißschuh --- drivers/platform/chrome/cros_ec_proto.c | 26 ++++++++++++++++++++++++++ include/linux/platform_data/cros_ec_proto.h | 2 ++ 2 files changed, 28 insertions(+) diff --git a/drivers/platform/chrome/cros_ec_proto.c b/drivers/platform/chrome/cros_ec_proto.c index fe68be66ee98..9cfe885a5301 100644 --- a/drivers/platform/chrome/cros_ec_proto.c +++ b/drivers/platform/chrome/cros_ec_proto.c @@ -1069,3 +1069,29 @@ int cros_ec_cmd_readmem(struct cros_ec_device *ec_dev, u8 offset, u8 size, void ¶ms, sizeof(params), dest, size); } EXPORT_SYMBOL_GPL(cros_ec_cmd_readmem); + +/** + * cros_ec_cmd_versions - Get supported version mask. + * + * @ec_dev: EC device + * @cmd: Command to test + * + * Return: version mask on success, negative error number on failure. + */ +int cros_ec_cmd_versions(struct cros_ec_device *ec_dev, u16 cmd) +{ + struct ec_params_get_cmd_versions_v1 req = {}; + struct ec_response_get_cmd_versions resp; + int ret; + + req.cmd = cmd; + ret = cros_ec_cmd(ec_dev, 1, EC_CMD_GET_CMD_VERSIONS, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret == -EINVAL) + return 0; /* Command not implemented */ + else if (ret < 0) + return ret; + else + return resp.version_mask; +} +EXPORT_SYMBOL_GPL(cros_ec_cmd_versions); diff --git a/include/linux/platform_data/cros_ec_proto.h b/include/linux/platform_data/cros_ec_proto.h index 6e9225bdf903..98ab5986f543 100644 --- a/include/linux/platform_data/cros_ec_proto.h +++ b/include/linux/platform_data/cros_ec_proto.h @@ -263,6 +263,8 @@ int cros_ec_cmd(struct cros_ec_device *ec_dev, unsigned int version, int command int cros_ec_cmd_readmem(struct cros_ec_device *ec_dev, u8 offset, u8 size, void *dest); +int cros_ec_cmd_versions(struct cros_ec_device *ec_dev, u16 cmd); + /** * cros_ec_get_time_ns() - Return time in ns. * From patchwork Sat Jun 8 08:12:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Patchwork-Id: 13690844 Received: from todd.t-8ch.de (todd.t-8ch.de [159.69.126.157]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3E2D8176AC8; Sat, 8 Jun 2024 08:12:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.69.126.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717834372; cv=none; b=QRdKdxSJcvjEnV/BurLn9HhAM+cDOH+CK6YiA40UoNbzAfRIVJL17U43RDy33dYydzow0cBSy50921yNaiKWbukv7eQmFa8sxQ49Vlb5yhaQs/8eBQCTDCh9RdB20ir5P4klDecaybvuOU4Gwnluavn3J/ogj9DeoDhJ+b1cAcI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717834372; c=relaxed/simple; bh=C6KO9oyesS6IVjxRm+VykrSOvpDomBKNbdZAZ0v59o0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=MpY160BdT/2jWaAwu9l+NNLVf1PIIdgOZKkwMXvCfH0YeWJ6362MjoWsIKO/48B/tt633FaN3kU+98wNyhFPue4Qm/AajoC8HRW1OifUrTP72iX+6DwMbj0gtaih+nZ0RUZAZ/rOKfplxHQDT49cQtKQ+mebAMmW/FlaF0V/x2o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net; spf=pass smtp.mailfrom=weissschuh.net; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b=NXHN7oz/; arc=none smtp.client-ip=159.69.126.157 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b="NXHN7oz/" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=weissschuh.net; s=mail; t=1717834365; bh=C6KO9oyesS6IVjxRm+VykrSOvpDomBKNbdZAZ0v59o0=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=NXHN7oz/2gN1zP49VsFsEgr8RIpDd6S4Ubu9r4VP1tO7N0DPHwiEjlE3bpLsK1vUw ujkqJVUKgjAjAqdXPbleP2UGsIpFnTxpcRFb/JnkfsimDmejL7DCVB1B7Luci61XVc oiTNaQxEoN6Qzi0DkDIFHbSczd/EOKxfvxdKA6tc= From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= Date: Sat, 08 Jun 2024 10:12:44 +0200 Subject: [PATCH 2/5] hwmon: (cros_ec) Add support for fan target speed Precedence: bulk X-Mailing-List: linux-hwmon@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240608-cros_ec-hwmon-pwm-v1-2-d29dfc26fbc3@weissschuh.net> References: <20240608-cros_ec-hwmon-pwm-v1-0-d29dfc26fbc3@weissschuh.net> In-Reply-To: <20240608-cros_ec-hwmon-pwm-v1-0-d29dfc26fbc3@weissschuh.net> To: Benson Leung , Tzung-Bi Shih , Guenter Roeck , =?utf-8?q?Thomas_Wei=C3=9Fschuh?= , Jean Delvare , Guenter Roeck Cc: Dustin Howett , Mario Limonciello , Stephen Horvath , chrome-platform@lists.linux.dev, linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, =?utf-8?q?Thoma?= =?utf-8?q?s_Wei=C3=9Fschuh?= X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1717834365; l=3031; i=linux@weissschuh.net; s=20221212; h=from:subject:message-id; bh=C6KO9oyesS6IVjxRm+VykrSOvpDomBKNbdZAZ0v59o0=; b=qv15PLsgwUIENgiYdWwPSzIS25Z85DAHXFdenwvAT21Qi8sWWX2iex+J9TubAm/k6QtX/Q6AI LyGfBnywpG5CY8kNtlj9phjYdCbyFv3Y9xxZZIMt/SHM0ozTkMBhqQ8 X-Developer-Key: i=linux@weissschuh.net; a=ed25519; pk=KcycQgFPX2wGR5azS7RhpBqedglOZVgRPfdFSPB1LNw= Use EC_CMD_PWM_GET_FAN_TARGET_RPM to retrieve the target fan speed. The CrOS EC only supports this for the first fan. Signed-off-by: Thomas Weißschuh --- Documentation/hwmon/cros_ec_hwmon.rst | 6 +++++- drivers/hwmon/cros_ec_hwmon.c | 26 +++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/Documentation/hwmon/cros_ec_hwmon.rst b/Documentation/hwmon/cros_ec_hwmon.rst index 47ecae983bdb..4aede331baeb 100644 --- a/Documentation/hwmon/cros_ec_hwmon.rst +++ b/Documentation/hwmon/cros_ec_hwmon.rst @@ -23,4 +23,8 @@ ChromeOS embedded controller used in Chromebooks and other devices. The channel labels exposed via hwmon are retrieved from the EC itself. -Fan and temperature readings are supported. +Supported features: + + - Current fan speed + - Target fan speed (for fan 1 only) + - Current temperature diff --git a/drivers/hwmon/cros_ec_hwmon.c b/drivers/hwmon/cros_ec_hwmon.c index 5514cf780b8b..09b8057e1223 100644 --- a/drivers/hwmon/cros_ec_hwmon.c +++ b/drivers/hwmon/cros_ec_hwmon.c @@ -36,6 +36,20 @@ static int cros_ec_hwmon_read_fan_speed(struct cros_ec_device *cros_ec, u8 index return 0; } +static int cros_ec_hwmon_read_fan_target(struct cros_ec_device *cros_ec, u16 *speed) +{ + struct ec_response_pwm_get_fan_rpm resp; + int ret; + + ret = cros_ec_cmd(cros_ec, 0, EC_CMD_PWM_GET_FAN_TARGET_RPM, + NULL, 0, &resp, sizeof(resp)); + if (ret < 0) + return ret; + + *speed = resp.rpm; + return 0; +} + static int cros_ec_hwmon_read_temp(struct cros_ec_device *cros_ec, u8 index, u8 *temp) { unsigned int offset; @@ -91,6 +105,11 @@ static int cros_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type, ret = cros_ec_hwmon_read_fan_speed(priv->cros_ec, channel, &speed); if (ret == 0) *val = cros_ec_hwmon_is_error_fan(speed); + + } else if (attr == hwmon_fan_target) { + ret = cros_ec_hwmon_read_fan_target(priv->cros_ec, &speed); + if (ret == 0) + *val = speed; } } else if (type == hwmon_temp) { if (attr == hwmon_temp_input) { @@ -128,8 +147,13 @@ static umode_t cros_ec_hwmon_is_visible(const void *data, enum hwmon_sensor_type u32 attr, int channel) { const struct cros_ec_hwmon_priv *priv = data; + u16 speed; if (type == hwmon_fan) { + if (attr == hwmon_fan_target && + cros_ec_hwmon_read_fan_target(priv->cros_ec, &speed) == -EOPNOTSUPP) + return 0; + if (priv->usable_fans & BIT(channel)) return 0444; } else if (type == hwmon_temp) { @@ -142,7 +166,7 @@ static umode_t cros_ec_hwmon_is_visible(const void *data, enum hwmon_sensor_type static const struct hwmon_channel_info * const cros_ec_hwmon_info[] = { HWMON_CHANNEL_INFO(fan, - HWMON_F_INPUT | HWMON_F_FAULT, + HWMON_F_INPUT | HWMON_F_FAULT | HWMON_F_TARGET, HWMON_F_INPUT | HWMON_F_FAULT, HWMON_F_INPUT | HWMON_F_FAULT, HWMON_F_INPUT | HWMON_F_FAULT), From patchwork Sat Jun 8 08:12:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Patchwork-Id: 13690843 Received: from todd.t-8ch.de (todd.t-8ch.de [159.69.126.157]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BFF5E176AB7; Sat, 8 Jun 2024 08:12:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.69.126.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717834372; cv=none; b=YOOU3S27LS8HzplwRQQHVfm4wTpf5gd6i/DHsYiysK3kmNpJbQZSz1VORNJx6YM02l0ucUSH1oM8CG3c6y2YACpzhCfCRjNEiyu1VYnCkxeoVNrpLNLTbfNeX9IzRmYRwlLZDFsATU+ydTLi+RcnA9PJMVCNpQdu6xgmxn9qNao= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717834372; c=relaxed/simple; bh=cey65pHupnRn7AKD1BC6IG+jnHBcwTWEUtCKuXY67cE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ETFtg1/zczP203P6/Bg0UwChYDzJpaw8H3n2y7mC9ZQ/we7Vu2Ut7nIHa3WnJbjeordg+vJM7Jernf3PdhXAg8dRxokCCw4SfaqUYooNm6idQzu25rjsmDaXRXeSyPRkqGTmHUlLQASeacbiWNko80qeodNyMmqBcRzSB5KNEu4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net; spf=pass smtp.mailfrom=weissschuh.net; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b=qo9Wgxe6; arc=none smtp.client-ip=159.69.126.157 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b="qo9Wgxe6" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=weissschuh.net; s=mail; t=1717834365; bh=cey65pHupnRn7AKD1BC6IG+jnHBcwTWEUtCKuXY67cE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=qo9Wgxe6BLPHOFk2WVMOAOGhyjN2H81WFz6tp0LF5UPh6D3YItwR1x5WoDWb7gHtZ 0q2PbEcbCYKEusDgQhfMshRbWfLzxKcYItq2X++iI+o3GeDreA+FN/Urq8Zw0E0JdH rxL+vkkhR6PTKtNlPI+u6rW6jxpXrdwyDbZsG4NU= From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= Date: Sat, 08 Jun 2024 10:12:45 +0200 Subject: [PATCH 3/5] hwmon: (cros_ec) Add support for PWM fan control Precedence: bulk X-Mailing-List: linux-hwmon@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240608-cros_ec-hwmon-pwm-v1-3-d29dfc26fbc3@weissschuh.net> References: <20240608-cros_ec-hwmon-pwm-v1-0-d29dfc26fbc3@weissschuh.net> In-Reply-To: <20240608-cros_ec-hwmon-pwm-v1-0-d29dfc26fbc3@weissschuh.net> To: Benson Leung , Tzung-Bi Shih , Guenter Roeck , =?utf-8?q?Thomas_Wei=C3=9Fschuh?= , Jean Delvare , Guenter Roeck Cc: Dustin Howett , Mario Limonciello , Stephen Horvath , chrome-platform@lists.linux.dev, linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, =?utf-8?q?Thoma?= =?utf-8?q?s_Wei=C3=9Fschuh?= X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1717834365; l=7057; i=linux@weissschuh.net; s=20221212; h=from:subject:message-id; bh=cey65pHupnRn7AKD1BC6IG+jnHBcwTWEUtCKuXY67cE=; b=1VITW0coHrRX9kNamlVH5dgZxBlx1VogdDAvGzhI9dZbRPF2D6Wj3X89dDPDTUz4x7MxU1RAg nPAkFVPSffcCOKVyXFm67ESIBZInt3AkC8ngZiqZAnbPHQKl5Kf1BGl X-Developer-Key: i=linux@weissschuh.net; a=ed25519; pk=KcycQgFPX2wGR5azS7RhpBqedglOZVgRPfdFSPB1LNw= Implement setting fan duty cycle and automatic management through EC_CMD_PWM_SET_FAN_DUTY and EC_CMD_THERMAL_AUTO_FAN_CTRL. The hardware does not support reading back the values again, so that is emulated in the driver. Signed-off-by: Thomas Weißschuh --- Documentation/hwmon/cros_ec_hwmon.rst | 1 + drivers/hwmon/cros_ec_hwmon.c | 128 +++++++++++++++++++++++++++++++++- 2 files changed, 127 insertions(+), 2 deletions(-) diff --git a/Documentation/hwmon/cros_ec_hwmon.rst b/Documentation/hwmon/cros_ec_hwmon.rst index 4aede331baeb..3cc345425aac 100644 --- a/Documentation/hwmon/cros_ec_hwmon.rst +++ b/Documentation/hwmon/cros_ec_hwmon.rst @@ -27,4 +27,5 @@ Supported features: - Current fan speed - Target fan speed (for fan 1 only) + - PWM-based fan control - Current temperature diff --git a/drivers/hwmon/cros_ec_hwmon.c b/drivers/hwmon/cros_ec_hwmon.c index 09b8057e1223..48b7073a4991 100644 --- a/drivers/hwmon/cros_ec_hwmon.c +++ b/drivers/hwmon/cros_ec_hwmon.c @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -17,10 +18,19 @@ #define DRV_NAME "cros-ec-hwmon" +enum cros_ec_hwmon_fan_mode { + cros_ec_hwmon_fan_mode_full = 0, + cros_ec_hwmon_fan_mode_manual = 1, + cros_ec_hwmon_fan_mode_auto = 2, +}; + struct cros_ec_hwmon_priv { struct cros_ec_device *cros_ec; const char *temp_sensor_names[EC_TEMP_SENSOR_ENTRIES + EC_TEMP_SENSOR_B_ENTRIES]; u8 usable_fans; + bool has_fan_pwm; + u8 fan_pwm[EC_FAN_SPEED_ENTRIES]; + enum cros_ec_hwmon_fan_mode fan_mode[EC_FAN_SPEED_ENTRIES]; }; static int cros_ec_hwmon_read_fan_speed(struct cros_ec_device *cros_ec, u8 index, u16 *speed) @@ -50,6 +60,27 @@ static int cros_ec_hwmon_read_fan_target(struct cros_ec_device *cros_ec, u16 *sp return 0; } +static int cros_ec_hwmon_set_fan_auto(struct cros_ec_device *cros_ec, u8 index) +{ + struct ec_params_auto_fan_ctrl_v1 req = { + .fan_idx = index, + }; + + return cros_ec_cmd(cros_ec, 1, EC_CMD_THERMAL_AUTO_FAN_CTRL, + &req, sizeof(req), NULL, 0); +} + +static int cros_ec_hwmon_set_fan_duty_cycle(struct cros_ec_device *cros_ec, u8 index, u8 percent) +{ + struct ec_params_pwm_set_fan_duty_v1 req = { + .fan_idx = index, + .percent = percent, + }; + + return cros_ec_cmd(cros_ec, 1, EC_CMD_PWM_SET_FAN_DUTY, + &req, sizeof(req), NULL, 0); +} + static int cros_ec_hwmon_read_temp(struct cros_ec_device *cros_ec, u8 index, u8 *temp) { unsigned int offset; @@ -111,6 +142,17 @@ static int cros_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type, if (ret == 0) *val = speed; } + + } else if (type == hwmon_pwm) { + if (attr == hwmon_pwm_input) { + *val = priv->fan_pwm[channel]; + ret = 0; + + } else if (attr == hwmon_pwm_enable) { + *val = priv->fan_mode[channel]; + ret = 0; + } + } else if (type == hwmon_temp) { if (attr == hwmon_temp_input) { ret = cros_ec_hwmon_read_temp(priv->cros_ec, channel, &temp); @@ -143,6 +185,61 @@ static int cros_ec_hwmon_read_string(struct device *dev, enum hwmon_sensor_types return -EOPNOTSUPP; } +static int cros_ec_hwmon_write_pwm_input(struct cros_ec_hwmon_priv *priv, int channel, long val) +{ + u8 percent; + int ret; + + if (val < 0 || val > 255) + return -EINVAL; + + percent = DIV_ROUND_CLOSEST(val * 100, 255); + + if (priv->fan_mode[channel] == cros_ec_hwmon_fan_mode_manual) { + ret = cros_ec_hwmon_set_fan_duty_cycle(priv->cros_ec, channel, percent); + if (ret < 0) + return ret; + } + + priv->fan_pwm[channel] = percent; + return 0; +} + +static int cros_ec_hwmon_write_pwm_enable(struct cros_ec_hwmon_priv *priv, int channel, long val) +{ + int ret; + + if (val == cros_ec_hwmon_fan_mode_full) + ret = cros_ec_hwmon_set_fan_duty_cycle(priv->cros_ec, channel, 100); + else if (val == cros_ec_hwmon_fan_mode_manual) + ret = cros_ec_hwmon_set_fan_duty_cycle(priv->cros_ec, channel, + priv->fan_pwm[channel]); + else if (val == cros_ec_hwmon_fan_mode_auto) + ret = cros_ec_hwmon_set_fan_auto(priv->cros_ec, channel); + else + return -EINVAL; + + priv->fan_mode[channel] = val; + return ret; +} + +static int cros_ec_hwmon_write(struct device *dev, enum hwmon_sensor_types type, + u32 attr, int channel, long val) +{ + struct cros_ec_hwmon_priv *priv = dev_get_drvdata(dev); + int ret = -EOPNOTSUPP; + + if (type == hwmon_pwm) { + if (attr == hwmon_pwm_input) + ret = cros_ec_hwmon_write_pwm_input(priv, channel, val); + + else if (attr == hwmon_pwm_enable) + ret = cros_ec_hwmon_write_pwm_enable(priv, channel, val); + } + + return ret; +} + static umode_t cros_ec_hwmon_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr, int channel) { @@ -156,6 +253,11 @@ static umode_t cros_ec_hwmon_is_visible(const void *data, enum hwmon_sensor_type if (priv->usable_fans & BIT(channel)) return 0444; + + } else if (type == hwmon_pwm) { + if (priv->has_fan_pwm && priv->usable_fans & BIT(channel)) + return 0644; + } else if (type == hwmon_temp) { if (priv->temp_sensor_names[channel]) return 0444; @@ -170,6 +272,11 @@ static const struct hwmon_channel_info * const cros_ec_hwmon_info[] = { HWMON_F_INPUT | HWMON_F_FAULT, HWMON_F_INPUT | HWMON_F_FAULT, HWMON_F_INPUT | HWMON_F_FAULT), + HWMON_CHANNEL_INFO(pwm, + HWMON_PWM_INPUT | HWMON_PWM_ENABLE, + HWMON_PWM_INPUT | HWMON_PWM_ENABLE, + HWMON_PWM_INPUT | HWMON_PWM_ENABLE, + HWMON_PWM_INPUT | HWMON_PWM_ENABLE), HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, @@ -201,6 +308,7 @@ static const struct hwmon_channel_info * const cros_ec_hwmon_info[] = { static const struct hwmon_ops cros_ec_hwmon_ops = { .read = cros_ec_hwmon_read, .read_string = cros_ec_hwmon_read_string, + .write = cros_ec_hwmon_write, .is_visible = cros_ec_hwmon_is_visible, }; @@ -249,10 +357,26 @@ static void cros_ec_hwmon_probe_fans(struct cros_ec_hwmon_priv *priv) size_t i; int ret; + ret = cros_ec_cmd_versions(priv->cros_ec, EC_CMD_PWM_SET_FAN_DUTY); + if (ret >= 0 && ret & EC_VER_MASK(1)) + priv->has_fan_pwm = 1; + for (i = 0; i < EC_FAN_SPEED_ENTRIES; i++) { ret = cros_ec_hwmon_read_fan_speed(priv->cros_ec, i, &speed); - if (ret == 0 && speed != EC_FAN_SPEED_NOT_PRESENT) - priv->usable_fans |= BIT(i); + if (ret < 0) + continue; + if (speed == EC_FAN_SPEED_NOT_PRESENT) + continue; + + priv->usable_fans |= BIT(i); + + if (priv->has_fan_pwm) { + priv->fan_mode[i] = cros_ec_hwmon_fan_mode_auto; + ret = cros_ec_hwmon_set_fan_auto(priv->cros_ec, i); + if (ret != 0) + priv->has_fan_pwm = 0; + } + } } From patchwork Sat Jun 8 08:12:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Patchwork-Id: 13690845 Received: from todd.t-8ch.de (todd.t-8ch.de [159.69.126.157]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 72E42176ABC; Sat, 8 Jun 2024 08:12:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.69.126.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717834372; cv=none; b=WWZVBmwih0CM9Sc/oYR8/zfHrWWGL+hNQWMWf6TKCnOZvV+qQKC3V/Cc8MsepDOBmVkTftE6GsE0VOIzKhPPc28trnj0GcrxOzbCdmz4o9uOf5aPTcJjSdR8MyeIIwMjAPmWLDdVGLMG+C3FHjxK1sAua8omNXruN/W04eQnrc0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717834372; c=relaxed/simple; bh=uOqrwTrndkshyrpD+eXmWOKCmadDalmhjImwkQ3pihs=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qXFjFPU4FMUBGrtBTnyLJc06Jn2lVJ74f/mXrE3TPdGsYFAVKisikCuTc8jd6/yyNgVluiEWR/b6+zBxa6/66LTIY8RA74aeBmq7mfOXq6nUlfJ930QKtFiZLGTNlc3gIYuw9rvhM6jCHlRUs0l57FLJK2lVfReKLn7RDUroz4w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net; spf=pass smtp.mailfrom=weissschuh.net; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b=gthcl2iv; arc=none smtp.client-ip=159.69.126.157 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b="gthcl2iv" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=weissschuh.net; s=mail; t=1717834365; bh=uOqrwTrndkshyrpD+eXmWOKCmadDalmhjImwkQ3pihs=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=gthcl2ivvcxPygDOG+vr7Mvnq8Lzvgyf+wRW7rujHo4L4uJn71ZiGX2bt9nGwgNhR 2W2qBRQLMaL6E+a9UXuIMcc71Bz16V0+Y86/oAiJt2jlPgZGd85H7gJC/qKNMPk8Xi /uQj+i4wOFQsysxPd91Sx/eVc3BwiY5YhpxZpLfs= From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= Date: Sat, 08 Jun 2024 10:12:46 +0200 Subject: [PATCH 4/5] hwmon: (cros_ec) Split temperature channel params Precedence: bulk X-Mailing-List: linux-hwmon@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240608-cros_ec-hwmon-pwm-v1-4-d29dfc26fbc3@weissschuh.net> References: <20240608-cros_ec-hwmon-pwm-v1-0-d29dfc26fbc3@weissschuh.net> In-Reply-To: <20240608-cros_ec-hwmon-pwm-v1-0-d29dfc26fbc3@weissschuh.net> To: Benson Leung , Tzung-Bi Shih , Guenter Roeck , =?utf-8?q?Thomas_Wei=C3=9Fschuh?= , Jean Delvare , Guenter Roeck Cc: Dustin Howett , Mario Limonciello , Stephen Horvath , chrome-platform@lists.linux.dev, linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, =?utf-8?q?Thoma?= =?utf-8?q?s_Wei=C3=9Fschuh?= X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1717834365; l=3087; i=linux@weissschuh.net; s=20221212; h=from:subject:message-id; bh=uOqrwTrndkshyrpD+eXmWOKCmadDalmhjImwkQ3pihs=; b=P+7vcuq9iT0rpTV+K/76Tt9+v2o4ROJUSLOOKUTiDuKyNcOJM4Ygo/GboDTHiDjbykWZzSM/H 4gdJPDR9fZtCZ16xtIg0H2ZkVSLbjMkQk6E7mMRYtXaVxW8wa+LGqgd X-Developer-Key: i=linux@weissschuh.net; a=ed25519; pk=KcycQgFPX2wGR5azS7RhpBqedglOZVgRPfdFSPB1LNw= An upcoming change will add more channel parameters. This leads to a lot of churn and very long lines. Use a macro to encapsulate all of the shared values. Signed-off-by: Thomas Weißschuh --- drivers/hwmon/cros_ec_hwmon.c | 50 ++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/drivers/hwmon/cros_ec_hwmon.c b/drivers/hwmon/cros_ec_hwmon.c index 48b7073a4991..5cddf78cfe0e 100644 --- a/drivers/hwmon/cros_ec_hwmon.c +++ b/drivers/hwmon/cros_ec_hwmon.c @@ -277,31 +277,33 @@ static const struct hwmon_channel_info * const cros_ec_hwmon_info[] = { HWMON_PWM_INPUT | HWMON_PWM_ENABLE, HWMON_PWM_INPUT | HWMON_PWM_ENABLE, HWMON_PWM_INPUT | HWMON_PWM_ENABLE), + +#define CROS_EC_HWMON_TEMP_PARAMS (HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL) HWMON_CHANNEL_INFO(temp, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL, - HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL), + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS, + CROS_EC_HWMON_TEMP_PARAMS), NULL }; From patchwork Sat Jun 8 08:12:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= X-Patchwork-Id: 13690848 Received: from todd.t-8ch.de (todd.t-8ch.de [159.69.126.157]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D92E5178362; Sat, 8 Jun 2024 08:12:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.69.126.157 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717834376; cv=none; b=Ymb55eDZh5AQosz3cwsequQ1EHvHLk41+L8uZcKviG39Q6KomtVNQpYQ4SuTt8dm2IXI2vigPvGnBI9HRIwHY3MkpIhMg35HpznKwlOGnFrJaqG5KBqtLbvECDfeugsyERm4sgQwYZyzu7/FknY3H72YQQAsCNbyR9Jax5OV7Cw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1717834376; c=relaxed/simple; bh=nS0VirJKyYW+dk8nu7ljo2kt+g/A4F+QJmGxE892J9I=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qLFJW8uSm63vwLtZGrHzFj5rigVlpiZmuXSEIW/qzVSU04htm4g4+jrLfUDlzSvidAi5ssebJ2jRiBfgeXa9P2ozyN0QqedWRV1ZsudApnTcZcFJbHHFnctcCs3/Trb1uaPQdktvY4DN4d4EKeFiMF5V+dgp7qtXjihnpr/i/JU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net; spf=pass smtp.mailfrom=weissschuh.net; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b=amJRXPqB; arc=none smtp.client-ip=159.69.126.157 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=weissschuh.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=weissschuh.net header.i=@weissschuh.net header.b="amJRXPqB" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=weissschuh.net; s=mail; t=1717834366; bh=nS0VirJKyYW+dk8nu7ljo2kt+g/A4F+QJmGxE892J9I=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=amJRXPqBn4lEkEK0kaAX1c495b7B/CEZvd0SVy1YL82RQn8qo0rRHrMfRGd2dyQhB yU+vmiGcBRZgKJO8+U5eATwjzx8ILmIMx7Kt1y61Whz/D93Q7MkHsOs+BUvr4rtlcR tde2QYQPm5yDepBSIj1SKa/+D2CDWZnax/p1z0PU= From: =?utf-8?q?Thomas_Wei=C3=9Fschuh?= Date: Sat, 08 Jun 2024 10:12:47 +0200 Subject: [PATCH 5/5] hwmon: (cros_ec) Add support for temperature thresholds Precedence: bulk X-Mailing-List: linux-hwmon@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-Id: <20240608-cros_ec-hwmon-pwm-v1-5-d29dfc26fbc3@weissschuh.net> References: <20240608-cros_ec-hwmon-pwm-v1-0-d29dfc26fbc3@weissschuh.net> In-Reply-To: <20240608-cros_ec-hwmon-pwm-v1-0-d29dfc26fbc3@weissschuh.net> To: Benson Leung , Tzung-Bi Shih , Guenter Roeck , =?utf-8?q?Thomas_Wei=C3=9Fschuh?= , Jean Delvare , Guenter Roeck Cc: Dustin Howett , Mario Limonciello , Stephen Horvath , chrome-platform@lists.linux.dev, linux-kernel@vger.kernel.org, linux-hwmon@vger.kernel.org, =?utf-8?q?Thoma?= =?utf-8?q?s_Wei=C3=9Fschuh?= X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1717834365; l=6121; i=linux@weissschuh.net; s=20221212; h=from:subject:message-id; bh=nS0VirJKyYW+dk8nu7ljo2kt+g/A4F+QJmGxE892J9I=; b=V5V/b7UZ6qurz6h+lVJBextsKc+zDESr+4BKzZqCx/SRGi4RrU7YqVnGRo32ivPUsbr34MEHs Ic103Au6TTsBxT6JaCsU8kxRJcn+szSC9XRcLDCmuaVvNq2zfbj6C96 X-Developer-Key: i=linux@weissschuh.net; a=ed25519; pk=KcycQgFPX2wGR5azS7RhpBqedglOZVgRPfdFSPB1LNw= Implement reading and writing temperature thresholds through EC_CMD_THERMAL_GET_THRESHOLD/EC_CMD_THERMAL_SET_THRESHOLD. Thresholds are mapped as follows between the EC and hwmon: hwmon_temp_max - EC_TEMP_THRESH_WARN hwmon_temp_crit - EC_TEMP_THRESH_HIGH hwmon_temp_emergency - EC_TEMP_THRESH_HALT Signed-off-by: Thomas Weißschuh --- Documentation/hwmon/cros_ec_hwmon.rst | 1 + drivers/hwmon/cros_ec_hwmon.c | 82 +++++++++++++++++++++++++++++++++-- 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/Documentation/hwmon/cros_ec_hwmon.rst b/Documentation/hwmon/cros_ec_hwmon.rst index 3cc345425aac..24ff261ae232 100644 --- a/Documentation/hwmon/cros_ec_hwmon.rst +++ b/Documentation/hwmon/cros_ec_hwmon.rst @@ -29,3 +29,4 @@ Supported features: - Target fan speed (for fan 1 only) - PWM-based fan control - Current temperature + - Temperature thresholds diff --git a/drivers/hwmon/cros_ec_hwmon.c b/drivers/hwmon/cros_ec_hwmon.c index 5cddf78cfe0e..009b94af6df4 100644 --- a/drivers/hwmon/cros_ec_hwmon.c +++ b/drivers/hwmon/cros_ec_hwmon.c @@ -29,6 +29,7 @@ struct cros_ec_hwmon_priv { const char *temp_sensor_names[EC_TEMP_SENSOR_ENTRIES + EC_TEMP_SENSOR_B_ENTRIES]; u8 usable_fans; bool has_fan_pwm; + bool has_temp_threshold; u8 fan_pwm[EC_FAN_SPEED_ENTRIES]; enum cros_ec_hwmon_fan_mode fan_mode[EC_FAN_SPEED_ENTRIES]; }; @@ -97,6 +98,42 @@ static int cros_ec_hwmon_read_temp(struct cros_ec_device *cros_ec, u8 index, u8 return 0; } +static int cros_ec_hwmon_read_temp_threshold(struct cros_ec_device *cros_ec, u8 index, + enum ec_temp_thresholds threshold, u32 *temp) +{ + struct ec_params_thermal_get_threshold_v1 req = {}; + struct ec_thermal_config resp; + int ret; + + req.sensor_num = index; + ret = cros_ec_cmd(cros_ec, 1, EC_CMD_THERMAL_GET_THRESHOLD, + &req, sizeof(req), &resp, sizeof(resp)); + if (ret < 0) + return ret; + + *temp = resp.temp_host[threshold]; + return 0; +} + +static int cros_ec_hwmon_write_temp_threshold(struct cros_ec_device *cros_ec, u8 index, + enum ec_temp_thresholds threshold, u32 temp) +{ + struct ec_params_thermal_get_threshold_v1 get_req = {}; + struct ec_params_thermal_set_threshold_v1 set_req = {}; + int ret; + + get_req.sensor_num = index; + ret = cros_ec_cmd(cros_ec, 1, EC_CMD_THERMAL_GET_THRESHOLD, + &get_req, sizeof(get_req), &set_req.cfg, sizeof(set_req.cfg)); + if (ret < 0) + return ret; + + set_req.sensor_num = index; + set_req.cfg.temp_host[threshold] = temp; + return cros_ec_cmd(cros_ec, 1, EC_CMD_THERMAL_SET_THRESHOLD, + &set_req, sizeof(set_req), NULL, 0); +} + static bool cros_ec_hwmon_is_error_fan(u16 speed) { return speed == EC_FAN_SPEED_NOT_PRESENT || speed == EC_FAN_SPEED_STALLED; @@ -115,11 +152,24 @@ static long cros_ec_hwmon_temp_to_millicelsius(u8 temp) return kelvin_to_millicelsius((((long)temp) + EC_TEMP_SENSOR_OFFSET)); } +static enum ec_temp_thresholds cros_ec_hwmon_attr_to_thres(u32 attr) +{ + if (attr == hwmon_temp_max) + return EC_TEMP_THRESH_WARN; + else if (attr == hwmon_temp_crit) + return EC_TEMP_THRESH_HIGH; + else if (attr == hwmon_temp_emergency) + return EC_TEMP_THRESH_HALT; + else + return 0; +} + static int cros_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long *val) { struct cros_ec_hwmon_priv *priv = dev_get_drvdata(dev); int ret = -EOPNOTSUPP; + u32 threshold; u16 speed; u8 temp; @@ -166,6 +216,14 @@ static int cros_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type, ret = cros_ec_hwmon_read_temp(priv->cros_ec, channel, &temp); if (ret == 0) *val = cros_ec_hwmon_is_error_temp(temp); + + } else if (attr == hwmon_temp_max || attr == hwmon_temp_crit || + attr == hwmon_temp_emergency) { + ret = cros_ec_hwmon_read_temp_threshold(priv->cros_ec, channel, + cros_ec_hwmon_attr_to_thres(attr), + &threshold); + if (ret == 0) + *val = kelvin_to_millicelsius(threshold); } } @@ -235,6 +293,10 @@ static int cros_ec_hwmon_write(struct device *dev, enum hwmon_sensor_types type, else if (attr == hwmon_pwm_enable) ret = cros_ec_hwmon_write_pwm_enable(priv, channel, val); + } else if (type == hwmon_temp) { + ret = cros_ec_hwmon_write_temp_threshold(priv->cros_ec, channel, + cros_ec_hwmon_attr_to_thres(attr), + millicelsius_to_kelvin(val)); } return ret; @@ -259,8 +321,16 @@ static umode_t cros_ec_hwmon_is_visible(const void *data, enum hwmon_sensor_type return 0644; } else if (type == hwmon_temp) { - if (priv->temp_sensor_names[channel]) - return 0444; + if (priv->temp_sensor_names[channel]) { + if (attr == hwmon_temp_max || + attr == hwmon_temp_crit || + attr == hwmon_temp_emergency) { + if (priv->has_temp_threshold) + return 0644; + } else { + return 0444; + } + } } return 0; @@ -278,7 +348,8 @@ static const struct hwmon_channel_info * const cros_ec_hwmon_info[] = { HWMON_PWM_INPUT | HWMON_PWM_ENABLE, HWMON_PWM_INPUT | HWMON_PWM_ENABLE), -#define CROS_EC_HWMON_TEMP_PARAMS (HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL) +#define CROS_EC_HWMON_TEMP_PARAMS (HWMON_T_INPUT | HWMON_T_FAULT | HWMON_T_LABEL | \ + HWMON_T_MAX | HWMON_T_CRIT | HWMON_T_EMERGENCY) HWMON_CHANNEL_INFO(temp, CROS_EC_HWMON_TEMP_PARAMS, CROS_EC_HWMON_TEMP_PARAMS, @@ -325,9 +396,14 @@ static void cros_ec_hwmon_probe_temp_sensors(struct device *dev, struct cros_ec_ struct ec_params_temp_sensor_get_info req = {}; struct ec_response_temp_sensor_get_info resp; size_t candidates, i, sensor_name_size; + u32 threshold; int ret; u8 temp; + ret = cros_ec_hwmon_read_temp_threshold(priv->cros_ec, 0, EC_TEMP_THRESH_HIGH, &threshold); + if (ret == 0) + priv->has_temp_threshold = 1; + if (thermal_version < 2) candidates = EC_TEMP_SENSOR_ENTRIES; else