From patchwork Tue Sep 15 16:50:59 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Punit Agrawal X-Patchwork-Id: 53691 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f72.google.com (mail-la0-f72.google.com [209.85.215.72]) by patches.linaro.org (Postfix) with ESMTPS id 2AD3822A0D for ; Tue, 15 Sep 2015 16:52:51 +0000 (UTC) Received: by lanb10 with SMTP id b10sf63153381lan.3 for ; Tue, 15 Sep 2015 09:52:50 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=OpBbrTShAta58Gtw+ktAAXnKYqZ5wthDqob+WS8J/C4=; b=mylj3QKMjWQcr5R4kGq3nJ0Ae5ACQU0ciuOmut1dXkMyzp+OBG5nR9pbZolQioFK1W mgvZ4lUMmkqH/iMhZrX2tuxHYs460eT2kUtybZeshIMpDsKjN2LmY/GIcJLMAX9NJUDq BNgWxOLX74954oaAc0FpL5ryLlLR75IzT4Oz5MHxMmcsNGpKPGZp5CJS0haFK21EDbSe 0od80zPrJ4MHxH/u4GrXR4kMJCPlEvuPng2B9PyIrsWnLxLf8XY86NMsAjilpqHeVvil T/tm3rLstFe2jIN1mZpCK1xavFU/9EO/43PFldZxRaCLgOMec4rskPBWG+8ywPMhP3vZ bBxw== X-Gm-Message-State: ALoCoQmnSQW5zao0bzCjTXBUEE+BlROPIgZk3lJPy5sJKr6BdmSn2mT5vMq4GUKoFHqivxHMf+D8 X-Received: by 10.180.8.135 with SMTP id r7mr1006582wia.0.1442335970134; Tue, 15 Sep 2015 09:52:50 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.43.136 with SMTP id w8ls327995lal.82.gmail; Tue, 15 Sep 2015 09:52:49 -0700 (PDT) X-Received: by 10.112.156.193 with SMTP id wg1mr22882131lbb.24.1442335969936; Tue, 15 Sep 2015 09:52:49 -0700 (PDT) Received: from mail-la0-f52.google.com (mail-la0-f52.google.com. [209.85.215.52]) by mx.google.com with ESMTPS id h11si14816179lbo.151.2015.09.15.09.52.49 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 15 Sep 2015 09:52:49 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.52 as permitted sender) client-ip=209.85.215.52; Received: by lanb10 with SMTP id b10so111194934lan.3 for ; Tue, 15 Sep 2015 09:52:49 -0700 (PDT) X-Received: by 10.112.125.134 with SMTP id mq6mr22912028lbb.19.1442335969776; Tue, 15 Sep 2015 09:52:49 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.59.35 with SMTP id w3csp1919426lbq; Tue, 15 Sep 2015 09:52:48 -0700 (PDT) X-Received: by 10.66.101.39 with SMTP id fd7mr48589647pab.3.1442335968424; Tue, 15 Sep 2015 09:52:48 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id nv1si33204916pbc.145.2015.09.15.09.52.47; Tue, 15 Sep 2015 09:52:48 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753587AbbIOQwn (ORCPT + 29 others); Tue, 15 Sep 2015 12:52:43 -0400 Received: from fw-tnat.cambridge.arm.com ([217.140.96.140]:56795 "EHLO cam-smtp0.cambridge.arm.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752108AbbIOQwj (ORCPT ); Tue, 15 Sep 2015 12:52:39 -0400 Received: from e105922-lin.cambridge.arm.com (e105922-lin.cambridge.arm.com [10.2.135.144]) by cam-smtp0.cambridge.arm.com (8.13.8/8.13.8) with SMTP id t8FGq6J9003062; Tue, 15 Sep 2015 17:52:06 +0100 Received: by e105922-lin.cambridge.arm.com (sSMTP sendmail emulation); Tue, 15 Sep 2015 17:52:06 +0100 From: Punit Agrawal To: linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org Cc: linux-kernel@vger.kernel.org, mark.rutland@arm.com, robh+dt@kernel.org, edubezval@gmail.com, sudeep.holla@arm.com, liviu.dudau@arm.com, linux@roeck-us.net, Punit Agrawal Subject: [PATCH v4 3/5] hwmon: Support sensors exported via ARM SCP interface Date: Tue, 15 Sep 2015 17:50:59 +0100 Message-Id: <1442335861-7282-4-git-send-email-punit.agrawal@arm.com> X-Mailer: git-send-email 2.5.1 In-Reply-To: <1442335861-7282-1-git-send-email-punit.agrawal@arm.com> References: <1442335861-7282-1-git-send-email-punit.agrawal@arm.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: punit.agrawal@arm.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.52 as permitted sender) smtp.mailfrom=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Create a driver to add support for SoC sensors exported by the System Control Processor (SCP) via the System Control and Power Interface (SCPI). The supported sensor types is one of voltage, temperature, current, and power. The sensor labels and values provided by the SCP are exported via the hwmon sysfs interface. Signed-off-by: Punit Agrawal Acked-by: Guenter Roeck Cc: Sudeep Holla --- Documentation/hwmon/scpi-hwmon | 33 ++++++++ drivers/hwmon/Kconfig | 8 ++ drivers/hwmon/Makefile | 1 + drivers/hwmon/scpi-hwmon.c | 186 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 228 insertions(+) create mode 100644 Documentation/hwmon/scpi-hwmon create mode 100644 drivers/hwmon/scpi-hwmon.c diff --git a/Documentation/hwmon/scpi-hwmon b/Documentation/hwmon/scpi-hwmon new file mode 100644 index 0000000..4cfcdf2d --- /dev/null +++ b/Documentation/hwmon/scpi-hwmon @@ -0,0 +1,33 @@ +Kernel driver scpi-hwmon +======================== + +Supported chips: + * Chips based on ARM System Control Processor Interface + Addresses scanned: - + Datasheet: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0922b/index.html + +Author: Punit Agrawal + +Description +----------- + +This driver supports hardware monitoring for SoC's based on the ARM +System Control Processor (SCP) implementing the System Control +Processor Interface (SCPI). The following sensor types are supported +by the SCP - + + * temperature + * voltage + * current + * power + +The SCP interface provides an API to query the available sensors and +their values which are then exported to userspace by this driver. + +Usage Notes +----------- + +The driver relies on device tree node to indicate the presence of SCPI +support in the kernel. See +Documentation/devicetree/bindings/arm/arm,scpi.txt for details of the +devicetree node. \ No newline at end of file diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index c7a4f09..4b94327 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -1551,6 +1551,14 @@ config SENSORS_VEXPRESS the ARM Ltd's Versatile Express platform. It can provide wide range of information like temperature, power, energy. +config SENSORS_ARM_SCPI + tristate "ARM SCPI Sensors" + depends on ARM_SCPI_PROTOCOL + help + This driver provides support for temperature, voltage, current + and power sensors available on ARM Ltd's SCP based platforms. The + actual number and type of sensors exported depend the platform. + config SENSORS_VIA_CPUTEMP tristate "VIA CPU temperature sensor" depends on X86 diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 8aba87f..4961710 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -150,6 +150,7 @@ obj-$(CONFIG_SENSORS_TMP421) += tmp421.o obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o obj-$(CONFIG_SENSORS_V2M_JUNO) += v2m-juno.o obj-$(CONFIG_SENSORS_VEXPRESS) += vexpress.o +obj-$(CONFIG_SENSORS_ARM_SCPI) += scpi-hwmon.o obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o obj-$(CONFIG_SENSORS_VIA686A) += via686a.o obj-$(CONFIG_SENSORS_VT1211) += vt1211.o diff --git a/drivers/hwmon/scpi-hwmon.c b/drivers/hwmon/scpi-hwmon.c new file mode 100644 index 0000000..c7d1d14 --- /dev/null +++ b/drivers/hwmon/scpi-hwmon.c @@ -0,0 +1,186 @@ +/* + * System Control and Power Interface(SCPI) based hwmon sensor driver + * + * Copyright (C) 2015 ARM Ltd. + * Punit Agrawal + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed "as is" WITHOUT ANY WARRANTY of any + * kind, whether express or implied; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include + +struct sensor_data { + struct scpi_sensor_info info; + struct device_attribute dev_attr_input; + struct device_attribute dev_attr_label; + char input[20]; + char label[20]; +}; + +struct scpi_sensors { + struct scpi_ops *scpi_ops; + struct sensor_data *data; + struct attribute **attrs; + struct attribute_group group; + const struct attribute_group *groups[2]; +}; + +/* hwmon callback functions */ +static ssize_t +scpi_show_sensor(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct scpi_sensors *scpi_sensors = dev_get_drvdata(dev); + struct scpi_ops *scpi_ops = scpi_sensors->scpi_ops; + struct sensor_data *sensor; + u32 value; + int ret; + + sensor = container_of(attr, struct sensor_data, dev_attr_input); + + ret = scpi_ops->sensor_get_value(sensor->info.sensor_id, &value); + if (ret) + return ret; + + return sprintf(buf, "%u\n", value); +} + +static ssize_t +scpi_show_label(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct sensor_data *sensor; + + sensor = container_of(attr, struct sensor_data, dev_attr_label); + + return sprintf(buf, "%s\n", sensor->info.name); +} + +static int scpi_hwmon_probe(struct platform_device *pdev) +{ + u16 nr_sensors, i; + int num_temp = 0, num_volt = 0, num_current = 0, num_power = 0; + struct scpi_ops *scpi_ops; + struct device *hwdev, *dev = &pdev->dev; + struct scpi_sensors *scpi_sensors; + int ret; + + scpi_ops = get_scpi_ops(); + if (!scpi_ops) + return -EPROBE_DEFER; + + ret = scpi_ops->sensor_get_capability(&nr_sensors); + if (ret) + return ret; + + if (!nr_sensors) + return -ENODEV; + + scpi_sensors = devm_kzalloc(dev, sizeof(*scpi_sensors), GFP_KERNEL); + if (!scpi_sensors) + return -ENOMEM; + + scpi_sensors->data = devm_kcalloc(dev, nr_sensors, + sizeof(*scpi_sensors->data), GFP_KERNEL); + if (!scpi_sensors->data) + return -ENOMEM; + + scpi_sensors->attrs = devm_kcalloc(dev, (nr_sensors * 2) + 1, + sizeof(*scpi_sensors->attrs), GFP_KERNEL); + if (!scpi_sensors->attrs) + return -ENOMEM; + + scpi_sensors->scpi_ops = scpi_ops; + + for (i = 0; i < nr_sensors; i++) { + struct sensor_data *sensor = &scpi_sensors->data[i]; + + ret = scpi_ops->sensor_get_info(i, &sensor->info); + if (ret) + return ret; + + switch (sensor->info.class) { + case TEMPERATURE: + snprintf(sensor->input, sizeof(sensor->input), + "temp%d_input", num_temp + 1); + snprintf(sensor->label, sizeof(sensor->input), + "temp%d_label", num_temp + 1); + num_temp++; + break; + case VOLTAGE: + snprintf(sensor->input, sizeof(sensor->input), + "in%d_input", num_volt); + snprintf(sensor->label, sizeof(sensor->input), + "in%d_label", num_volt); + num_volt++; + break; + case CURRENT: + snprintf(sensor->input, sizeof(sensor->input), + "curr%d_input", num_current + 1); + snprintf(sensor->label, sizeof(sensor->input), + "curr%d_label", num_current + 1); + num_current++; + break; + case POWER: + snprintf(sensor->input, sizeof(sensor->input), + "power%d_input", num_power + 1); + snprintf(sensor->label, sizeof(sensor->input), + "power%d_label", num_power + 1); + num_power++; + break; + default: + break; + } + + sensor->dev_attr_input.attr.mode = S_IRUGO; + sensor->dev_attr_input.show = scpi_show_sensor; + sensor->dev_attr_input.attr.name = sensor->input; + + sensor->dev_attr_label.attr.mode = S_IRUGO; + sensor->dev_attr_label.show = scpi_show_label; + sensor->dev_attr_label.attr.name = sensor->label; + + scpi_sensors->attrs[i << 1] = &sensor->dev_attr_input.attr; + scpi_sensors->attrs[(i << 1) + 1] = &sensor->dev_attr_label.attr; + + sysfs_attr_init(scpi_sensors->attrs[i << 1]); + sysfs_attr_init(scpi_sensors->attrs[(i << 1) + 1]); + } + + scpi_sensors->group.attrs = scpi_sensors->attrs; + scpi_sensors->groups[0] = &scpi_sensors->group; + + hwdev = devm_hwmon_device_register_with_groups(dev, + "scpi_sensors", scpi_sensors, scpi_sensors->groups); + + return PTR_ERR_OR_ZERO(hwdev); +} + +static const struct of_device_id scpi_of_match[] = { + {.compatible = "arm,scpi-sensors"}, + {}, +}; + +static struct platform_driver scpi_hwmon_platdrv = { + .driver = { + .name = "scpi-hwmon", + .owner = THIS_MODULE, + .of_match_table = scpi_of_match, + }, + .probe = scpi_hwmon_probe, +}; +module_platform_driver(scpi_hwmon_platdrv); + +MODULE_AUTHOR("Punit Agrawal "); +MODULE_DESCRIPTION("ARM SCPI HWMON interface driver"); +MODULE_LICENSE("GPL v2");