2017-07-24 18:39:16

by Mikko Perttunen

[permalink] [raw]
Subject: [PATCH v2 1/5] arm64: tegra: Add BPMP thermal sensor to Tegra186

This adds the thermal sensor device provided by the BPMP, and the
relevant thermal sensors to the Tegra186 device tree.

Signed-off-by: Mikko Perttunen <[email protected]>
---
v2:
- added trips and cooling-maps nodes
arch/arm64/boot/dts/nvidia/tegra186.dtsi | 103 +++++++++++++++++++++++++++++++
1 file changed, 103 insertions(+)

diff --git a/arch/arm64/boot/dts/nvidia/tegra186.dtsi b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
index 0b0552c9f7dd..6adcf25e13d1 100644
--- a/arch/arm64/boot/dts/nvidia/tegra186.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra186.dtsi
@@ -4,6 +4,7 @@
#include <dt-bindings/mailbox/tegra186-hsp.h>
#include <dt-bindings/power/tegra186-powergate.h>
#include <dt-bindings/reset/tegra186-reset.h>
+#include <dt-bindings/thermal/tegra186-bpmp-thermal.h>

/ {
compatible = "nvidia,tegra186";
@@ -451,6 +452,108 @@
#size-cells = <0>;
status = "disabled";
};
+
+ bpmp_thermal: thermal {
+ compatible = "nvidia,tegra186-bpmp-thermal";
+ #thermal-sensor-cells = <1>;
+ };
+ };
+
+ thermal-zones {
+ a57 {
+ polling-delay = <0>;
+ polling-delay-passive = <1000>;
+
+ thermal-sensors =
+ <&bpmp_thermal TEGRA186_BPMP_THERMAL_ZONE_CPU>;
+
+ trips {
+ critical {
+ temperature = <101000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ };
+ };
+
+ denver {
+ polling-delay = <0>;
+ polling-delay-passive = <1000>;
+
+ thermal-sensors =
+ <&bpmp_thermal TEGRA186_BPMP_THERMAL_ZONE_AUX>;
+
+ trips {
+ critical {
+ temperature = <101000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ };
+ };
+
+ gpu {
+ polling-delay = <0>;
+ polling-delay-passive = <1000>;
+
+ thermal-sensors =
+ <&bpmp_thermal TEGRA186_BPMP_THERMAL_ZONE_GPU>;
+
+ trips {
+ critical {
+ temperature = <101000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ };
+ };
+
+ pll {
+ polling-delay = <0>;
+ polling-delay-passive = <1000>;
+
+ thermal-sensors =
+ <&bpmp_thermal TEGRA186_BPMP_THERMAL_ZONE_PLLX>;
+
+ trips {
+ critical {
+ temperature = <101000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ };
+ };
+
+ always_on {
+ polling-delay = <0>;
+ polling-delay-passive = <1000>;
+
+ thermal-sensors =
+ <&bpmp_thermal TEGRA186_BPMP_THERMAL_ZONE_AO>;
+
+ trips {
+ critical {
+ temperature = <101000>;
+ hysteresis = <0>;
+ type = "critical";
+ };
+ };
+
+ cooling-maps {
+ };
+ };
};

timer {
--
2.13.3


2017-07-24 17:41:12

by Mikko Perttunen

[permalink] [raw]
Subject: [PATCH v2 2/5] dt-bindings: Add bindings for nvidia,tegra186-bpmp-thermal

In Tegra186, the BPMP (Boot and Power Management Processor) implements
an interface that is used to read system temperatures, including CPU
cluster and GPU temperatures. This binding describes the thermal sensor
that is exposed by BPMP.

Signed-off-by: Mikko Perttunen <[email protected]>
Acked-by: Rob Herring <[email protected]>
---
.../thermal/nvidia,tegra186-bpmp-thermal.txt | 32 ++++++++++++++++++++++
.../dt-bindings/thermal/tegra186-bpmp-thermal.h | 14 ++++++++++
2 files changed, 46 insertions(+)
create mode 100644 Documentation/devicetree/bindings/thermal/nvidia,tegra186-bpmp-thermal.txt
create mode 100644 include/dt-bindings/thermal/tegra186-bpmp-thermal.h

diff --git a/Documentation/devicetree/bindings/thermal/nvidia,tegra186-bpmp-thermal.txt b/Documentation/devicetree/bindings/thermal/nvidia,tegra186-bpmp-thermal.txt
new file mode 100644
index 000000000000..276387dd6815
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/nvidia,tegra186-bpmp-thermal.txt
@@ -0,0 +1,32 @@
+NVIDIA Tegra186 BPMP thermal sensor
+
+In Tegra186, the BPMP (Boot and Power Management Processor) implements an
+interface that is used to read system temperatures, including CPU cluster
+and GPU temperatures. This binding describes the thermal sensor that is
+exposed by BPMP.
+
+The BPMP thermal node must be located directly inside the main BPMP node. See
+../firmware/nvidia,tegra186-bpmp.txt for details of the BPMP binding.
+
+This node represents a thermal sensor. See thermal.txt for details of the
+core thermal binding.
+
+Required properties:
+- compatible:
+ Array of strings.
+ One of:
+ - "nvidia,tegra186-bpmp-thermal".
+- #thermal-sensor-cells: Cell for sensor index.
+ Single-cell integer.
+ Must be <1>.
+
+Example:
+
+bpmp {
+ ...
+
+ bpmp_thermal: thermal {
+ compatible = "nvidia,tegra186-bpmp-thermal";
+ #thermal-sensor-cells = <1>;
+ };
+};
diff --git a/include/dt-bindings/thermal/tegra186-bpmp-thermal.h b/include/dt-bindings/thermal/tegra186-bpmp-thermal.h
new file mode 100644
index 000000000000..a96b8fa31aab
--- /dev/null
+++ b/include/dt-bindings/thermal/tegra186-bpmp-thermal.h
@@ -0,0 +1,14 @@
+/*
+ * This header provides constants for binding nvidia,tegra186-bpmp-thermal.
+ */
+
+#ifndef _DT_BINDINGS_THERMAL_TEGRA186_BPMP_THERMAL_H
+#define _DT_BINDINGS_THERMAL_TEGRA186_BPMP_THERMAL_H
+
+#define TEGRA186_BPMP_THERMAL_ZONE_CPU 2
+#define TEGRA186_BPMP_THERMAL_ZONE_GPU 3
+#define TEGRA186_BPMP_THERMAL_ZONE_AUX 4
+#define TEGRA186_BPMP_THERMAL_ZONE_PLLX 5
+#define TEGRA186_BPMP_THERMAL_ZONE_AO 6
+
+#endif
--
2.13.3

2017-07-24 17:51:42

by Mikko Perttunen

[permalink] [raw]
Subject: [PATCH v2 3/5] firmware: tegra: Expose tegra_bpmp_mrq_return

Expose and export the tegra_bpmp_mrq_return function for use of drivers
outside the core BPMP driver. This function is used to reply to
messages originating from the BPMP, which is required in the thermal
driver.

Signed-off-by: Mikko Perttunen <[email protected]>
---
drivers/firmware/tegra/bpmp.c | 5 +++--
include/soc/tegra/bpmp.h | 2 ++
2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
index b25179517cc5..53996a33a863 100644
--- a/drivers/firmware/tegra/bpmp.c
+++ b/drivers/firmware/tegra/bpmp.c
@@ -387,8 +387,8 @@ static struct tegra_bpmp_mrq *tegra_bpmp_find_mrq(struct tegra_bpmp *bpmp,
return NULL;
}

-static void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel,
- int code, const void *data, size_t size)
+void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code,
+ const void *data, size_t size)
{
unsigned long flags = channel->ib->flags;
struct tegra_bpmp *bpmp = channel->bpmp;
@@ -426,6 +426,7 @@ static void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel,
mbox_client_txdone(bpmp->mbox.channel, 0);
}
}
+EXPORT_SYMBOL_GPL(tegra_bpmp_mrq_return);

static void tegra_bpmp_handle_mrq(struct tegra_bpmp *bpmp,
unsigned int mrq,
diff --git a/include/soc/tegra/bpmp.h b/include/soc/tegra/bpmp.h
index 9ba65222bd3f..16d36dfe9fcd 100644
--- a/include/soc/tegra/bpmp.h
+++ b/include/soc/tegra/bpmp.h
@@ -117,6 +117,8 @@ int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
struct tegra_bpmp_message *msg);
int tegra_bpmp_transfer(struct tegra_bpmp *bpmp,
struct tegra_bpmp_message *msg);
+void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel, int code,
+ const void *data, size_t size);

int tegra_bpmp_request_mrq(struct tegra_bpmp *bpmp, unsigned int mrq,
tegra_bpmp_mrq_handler_t handler, void *data);
--
2.13.3

2017-07-24 17:55:32

by Mikko Perttunen

[permalink] [raw]
Subject: [PATCH v2 5/5] thermal: Add Tegra BPMP thermal sensor driver

On Tegra186, the BPMP (Boot and Power Management Processor) exposes an
interface to thermal sensors on the system-on-chip. This driver
implements access to the interface. It supports reading the
temperature, setting trip points and receiving notification of a
tripped trip point.

Signed-off-by: Mikko Perttunen <[email protected]>
---
v2:
- don't allocate space for disabled zones
- allow compilation with COMPILE_TEST

drivers/thermal/Makefile | 2 +-
drivers/thermal/tegra/Kconfig | 7 +
drivers/thermal/tegra/Makefile | 3 +-
drivers/thermal/tegra/bpmp-thermal.c | 263 +++++++++++++++++++++++++++++++++++
4 files changed, 273 insertions(+), 2 deletions(-)
create mode 100644 drivers/thermal/tegra/bpmp-thermal.c

diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index 094d7039981c..c03dccdba7b8 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -54,7 +54,7 @@ obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) += intel_bxt_pmic_thermal.o
obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
obj-$(CONFIG_ST_THERMAL) += st/
obj-$(CONFIG_QCOM_TSENS) += qcom/
-obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
+obj-y += tegra/
obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
diff --git a/drivers/thermal/tegra/Kconfig b/drivers/thermal/tegra/Kconfig
index cec586ec7e4b..f8740f7852e3 100644
--- a/drivers/thermal/tegra/Kconfig
+++ b/drivers/thermal/tegra/Kconfig
@@ -10,4 +10,11 @@ config TEGRA_SOCTHERM
zones to manage temperatures. This option is also required for the
emergency thermal reset (thermtrip) feature to function.

+config TEGRA_BPMP_THERMAL
+ tristate "Tegra BPMP thermal sensing"
+ depends on TEGRA_BPMP || COMPILE_TEST
+ help
+ Enable this option for support for sensing system temperature of NVIDIA
+ Tegra systems-on-chip with the BPMP coprocessor (Tegra186).
+
endmenu
diff --git a/drivers/thermal/tegra/Makefile b/drivers/thermal/tegra/Makefile
index 1ce1af2cf0f5..757abcd1feaf 100644
--- a/drivers/thermal/tegra/Makefile
+++ b/drivers/thermal/tegra/Makefile
@@ -1,4 +1,5 @@
-obj-$(CONFIG_TEGRA_SOCTHERM) += tegra-soctherm.o
+obj-$(CONFIG_TEGRA_SOCTHERM) += tegra-soctherm.o
+obj-$(CONFIG_TEGRA_BPMP_THERMAL) += bpmp-thermal.o

tegra-soctherm-y := soctherm.o soctherm-fuse.o
tegra-soctherm-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124-soctherm.o
diff --git a/drivers/thermal/tegra/bpmp-thermal.c b/drivers/thermal/tegra/bpmp-thermal.c
new file mode 100644
index 000000000000..b0980dbca3b3
--- /dev/null
+++ b/drivers/thermal/tegra/bpmp-thermal.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights reserved.
+ *
+ * Author:
+ * Mikko Perttunen <[email protected]>
+ * Aapo Vienamo <[email protected]>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+#include <linux/workqueue.h>
+
+#include <soc/tegra/bpmp.h>
+#include <soc/tegra/bpmp-abi.h>
+
+struct tegra_bpmp_thermal_zone {
+ struct tegra_bpmp_thermal *tegra;
+ struct thermal_zone_device *tzd;
+ struct work_struct tz_device_update_work;
+ unsigned int idx;
+};
+
+struct tegra_bpmp_thermal {
+ struct device *dev;
+ struct tegra_bpmp *bpmp;
+ unsigned int num_zones;
+ struct tegra_bpmp_thermal_zone **zones;
+};
+
+static int tegra_bpmp_thermal_get_temp(void *data, int *out_temp)
+{
+ struct tegra_bpmp_thermal_zone *zone = data;
+ struct mrq_thermal_host_to_bpmp_request req;
+ union mrq_thermal_bpmp_to_host_response reply;
+ struct tegra_bpmp_message msg;
+ int err;
+
+ memset(&req, 0, sizeof(req));
+ req.type = CMD_THERMAL_GET_TEMP;
+ req.get_temp.zone = zone->idx;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.mrq = MRQ_THERMAL;
+ msg.tx.data = &req;
+ msg.tx.size = sizeof(req);
+ msg.rx.data = &reply;
+ msg.rx.size = sizeof(reply);
+
+ err = tegra_bpmp_transfer(zone->tegra->bpmp, &msg);
+ if (err)
+ return err;
+
+ *out_temp = reply.get_temp.temp;
+
+ return 0;
+}
+
+static int tegra_bpmp_thermal_set_trips(void *data, int low, int high)
+{
+ struct tegra_bpmp_thermal_zone *zone = data;
+ struct mrq_thermal_host_to_bpmp_request req;
+ struct tegra_bpmp_message msg;
+
+ memset(&req, 0, sizeof(req));
+ req.type = CMD_THERMAL_SET_TRIP;
+ req.set_trip.zone = zone->idx;
+ req.set_trip.enabled = true;
+ req.set_trip.low = low;
+ req.set_trip.high = high;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.mrq = MRQ_THERMAL;
+ msg.tx.data = &req;
+ msg.tx.size = sizeof(req);
+
+ return tegra_bpmp_transfer(zone->tegra->bpmp, &msg);
+}
+
+static void tz_device_update_work_fn(struct work_struct *work)
+{
+ struct tegra_bpmp_thermal_zone *zone;
+
+ zone = container_of(work, struct tegra_bpmp_thermal_zone,
+ tz_device_update_work);
+
+ thermal_zone_device_update(zone->tzd, THERMAL_TRIP_VIOLATED);
+}
+
+static void bpmp_mrq_thermal(unsigned int mrq, struct tegra_bpmp_channel *ch,
+ void *data)
+{
+ struct mrq_thermal_bpmp_to_host_request *req;
+ struct tegra_bpmp_thermal *tegra = data;
+ int i;
+
+ req = (struct mrq_thermal_bpmp_to_host_request *)ch->ib->data;
+
+ if (req->type != CMD_THERMAL_HOST_TRIP_REACHED) {
+ dev_err(tegra->dev, "%s: invalid request type: %d\n",
+ __func__, req->type);
+ tegra_bpmp_mrq_return(ch, -EINVAL, NULL, 0);
+ return;
+ }
+
+ for (i = 0; i < tegra->num_zones; ++i) {
+ if (tegra->zones[i]->idx != req->host_trip_reached.zone)
+ continue;
+
+ schedule_work(&tegra->zones[i]->tz_device_update_work);
+ tegra_bpmp_mrq_return(ch, 0, NULL, 0);
+ return;
+ }
+
+ dev_err(tegra->dev, "%s: invalid thermal zone: %d\n", __func__,
+ req->host_trip_reached.zone);
+ tegra_bpmp_mrq_return(ch, -EINVAL, NULL, 0);
+}
+
+static int tegra_bpmp_thermal_get_num_zones(struct tegra_bpmp *bpmp,
+ int *num_zones)
+{
+ struct mrq_thermal_host_to_bpmp_request req;
+ union mrq_thermal_bpmp_to_host_response reply;
+ struct tegra_bpmp_message msg;
+ int err;
+
+ memset(&req, 0, sizeof(req));
+ req.type = CMD_THERMAL_GET_NUM_ZONES;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.mrq = MRQ_THERMAL;
+ msg.tx.data = &req;
+ msg.tx.size = sizeof(req);
+ msg.rx.data = &reply;
+ msg.rx.size = sizeof(reply);
+
+ err = tegra_bpmp_transfer(bpmp, &msg);
+ if (err)
+ return err;
+
+ *num_zones = reply.get_num_zones.num;
+
+ return 0;
+}
+
+static const struct thermal_zone_of_device_ops tegra_bpmp_of_thermal_ops = {
+ .get_temp = tegra_bpmp_thermal_get_temp,
+ .set_trips = tegra_bpmp_thermal_set_trips,
+};
+
+static int tegra_bpmp_thermal_probe(struct platform_device *pdev)
+{
+ struct tegra_bpmp *bpmp = dev_get_drvdata(pdev->dev.parent);
+ struct tegra_bpmp_thermal *tegra;
+ struct thermal_zone_device *tzd;
+ unsigned int i, max_num_zones;
+ int err;
+
+ tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra), GFP_KERNEL);
+ if (!tegra)
+ return -ENOMEM;
+
+ tegra->dev = &pdev->dev;
+ tegra->bpmp = bpmp;
+
+ err = tegra_bpmp_thermal_get_num_zones(bpmp, &max_num_zones);
+ if (err) {
+ dev_err(&pdev->dev, "failed to get the number of zones: %d\n",
+ err);
+ return err;
+ }
+
+ tegra->zones = devm_kcalloc(&pdev->dev, max_num_zones,
+ sizeof(*tegra->zones), GFP_KERNEL);
+ if (!tegra->zones)
+ return -ENOMEM;
+
+ for (i = 0; i < max_num_zones; ++i) {
+ struct tegra_bpmp_thermal_zone *zone;
+ int temp;
+
+ zone = devm_kzalloc(&pdev->dev, sizeof(*zone), GFP_KERNEL);
+ if (!zone)
+ return -ENOMEM;
+
+ zone->idx = i;
+ zone->tegra = tegra;
+
+ err = tegra_bpmp_thermal_get_temp(zone, &temp);
+ if (err < 0) {
+ devm_kfree(&pdev->dev, zone);
+ continue;
+ }
+
+ tzd = devm_thermal_zone_of_sensor_register(
+ &pdev->dev, i, zone, &tegra_bpmp_of_thermal_ops);
+ if (IS_ERR(tzd)) {
+ if (PTR_ERR(tzd) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ devm_kfree(&pdev->dev, zone);
+ continue;
+ }
+
+ zone->tzd = tzd;
+ INIT_WORK(&zone->tz_device_update_work,
+ tz_device_update_work_fn);
+
+ tegra->zones[tegra->num_zones++] = zone;
+ }
+
+ err = tegra_bpmp_request_mrq(bpmp, MRQ_THERMAL, bpmp_mrq_thermal,
+ tegra);
+ if (err) {
+ dev_err(&pdev->dev, "failed to register mrq handler: %d\n",
+ err);
+ return err;
+ }
+
+ platform_set_drvdata(pdev, tegra);
+
+ return 0;
+}
+
+static int tegra_bpmp_thermal_remove(struct platform_device *pdev)
+{
+ struct tegra_bpmp_thermal *tegra = platform_get_drvdata(pdev);
+
+ tegra_bpmp_free_mrq(tegra->bpmp, MRQ_THERMAL, tegra);
+
+ return 0;
+}
+
+static const struct of_device_id tegra_bpmp_thermal_of_match[] = {
+ { .compatible = "nvidia,tegra186-bpmp-thermal" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, tegra_bpmp_thermal_of_match);
+
+static struct platform_driver tegra_bpmp_thermal_driver = {
+ .probe = tegra_bpmp_thermal_probe,
+ .remove = tegra_bpmp_thermal_remove,
+ .driver = {
+ .name = "tegra-bpmp-thermal",
+ .of_match_table = tegra_bpmp_thermal_of_match,
+ },
+};
+module_platform_driver(tegra_bpmp_thermal_driver);
+
+MODULE_AUTHOR("Mikko Perttunen <[email protected]>");
+MODULE_DESCRIPTION("NVIDIA Tegra BPMP thermal sensor driver");
+MODULE_LICENSE("GPL v2");
--
2.13.3

2017-07-24 18:17:42

by Mikko Perttunen

[permalink] [raw]
Subject: [PATCH v2 4/5] firmware: tegra: Add stubs when BPMP not enabled

Add static inline stubs to bpmp.h when CONFIG_BPMP is not enabled.
This allows building BPMP-related drivers with COMPILE_TEST.

Signed-off-by: Mikko Perttunen <[email protected]>
---
v2:
- added patch

include/soc/tegra/bpmp.h | 42 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/include/soc/tegra/bpmp.h b/include/soc/tegra/bpmp.h
index 16d36dfe9fcd..4f9adb7790cc 100644
--- a/include/soc/tegra/bpmp.h
+++ b/include/soc/tegra/bpmp.h
@@ -96,9 +96,6 @@ struct tegra_bpmp {
struct genpd_onecell_data genpd;
};

-struct tegra_bpmp *tegra_bpmp_get(struct device *dev);
-void tegra_bpmp_put(struct tegra_bpmp *bpmp);
-
struct tegra_bpmp_message {
unsigned int mrq;

@@ -113,6 +110,9 @@ struct tegra_bpmp_message {
} rx;
};

+#if IS_ENABLED(CONFIG_TEGRA_BPMP)
+struct tegra_bpmp *tegra_bpmp_get(struct device *dev);
+void tegra_bpmp_put(struct tegra_bpmp *bpmp);
int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
struct tegra_bpmp_message *msg);
int tegra_bpmp_transfer(struct tegra_bpmp *bpmp,
@@ -124,6 +124,42 @@ int tegra_bpmp_request_mrq(struct tegra_bpmp *bpmp, unsigned int mrq,
tegra_bpmp_mrq_handler_t handler, void *data);
void tegra_bpmp_free_mrq(struct tegra_bpmp *bpmp, unsigned int mrq,
void *data);
+#else
+static inline struct tegra_bpmp *tegra_bpmp_get(struct device *dev)
+{
+ return ERR_PTR(-ENOTSUPP);
+}
+static inline void tegra_bpmp_put(struct tegra_bpmp *bpmp)
+{
+}
+static inline int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
+ struct tegra_bpmp_message *msg)
+{
+ return -ENOTSUPP;
+}
+static inline int tegra_bpmp_transfer(struct tegra_bpmp *bpmp,
+ struct tegra_bpmp_message *msg)
+{
+ return -ENOTSUPP;
+}
+static inline void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel,
+ int code, const void *data,
+ size_t size)
+{
+}
+
+static inline int tegra_bpmp_request_mrq(struct tegra_bpmp *bpmp,
+ unsigned int mrq,
+ tegra_bpmp_mrq_handler_t handler,
+ void *data)
+{
+ return -ENOTSUPP;
+}
+static inline void tegra_bpmp_free_mrq(struct tegra_bpmp *bpmp,
+ unsigned int mrq, void *data)
+{
+}
+#endif

#if IS_ENABLED(CONFIG_CLK_TEGRA_BPMP)
int tegra_bpmp_init_clocks(struct tegra_bpmp *bpmp);
--
2.13.3

2017-07-27 06:47:40

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v2 1/5] arm64: tegra: Add BPMP thermal sensor to Tegra186

Hi Mikko,

[auto build test ERROR on tegra/for-next]
[also build test ERROR on v4.13-rc2 next-20170726]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url: https://github.com/0day-ci/linux/commits/Mikko-Perttunen/arm64-tegra-Add-BPMP-thermal-sensor-to-Tegra186/20170726-055759
base: https://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git for-next
config: arm64-allnoconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
reproduce:
wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=arm64

Note: the linux-review/Mikko-Perttunen/arm64-tegra-Add-BPMP-thermal-sensor-to-Tegra186/20170726-055759 HEAD 2aebe2225f7f5f03abf6098e07387fa011ec16a8 builds fine.
It only hurts bisectibility.

All errors (new ones prefixed by >>):

In file included from arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi:1:0,
from arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts:5:
>> arch/arm64/boot/dts/nvidia/tegra186.dtsi:7:55: fatal error: dt-bindings/thermal/tegra186-bpmp-thermal.h: No such file or directory
#include <dt-bindings/thermal/tegra186-bpmp-thermal.h>
^
compilation terminated.

vim +7 arch/arm64/boot/dts/nvidia/tegra186.dtsi

> 7 #include <dt-bindings/thermal/tegra186-bpmp-thermal.h>
8

---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation


Attachments:
(No filename) (1.68 kB)
.config.gz (6.40 kB)
Download all attachments

2017-07-27 06:52:18

by Mikko Perttunen

[permalink] [raw]
Subject: Re: [PATCH v2 1/5] arm64: tegra: Add BPMP thermal sensor to Tegra186

Good point, so patches 1/5 and 2/5 should be swapped around.

Mikko

On 27.07.2017 09:47, kbuild test robot wrote:
> Hi Mikko,
>
> [auto build test ERROR on tegra/for-next]
> [also build test ERROR on v4.13-rc2 next-20170726]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>
> url: https://github.com/0day-ci/linux/commits/Mikko-Perttunen/arm64-tegra-Add-BPMP-thermal-sensor-to-Tegra186/20170726-055759
> base: https://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git for-next
> config: arm64-allnoconfig (attached as .config)
> compiler: aarch64-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
> reproduce:
> wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # save the attached .config to linux build tree
> make.cross ARCH=arm64
>
> Note: the linux-review/Mikko-Perttunen/arm64-tegra-Add-BPMP-thermal-sensor-to-Tegra186/20170726-055759 HEAD 2aebe2225f7f5f03abf6098e07387fa011ec16a8 builds fine.
> It only hurts bisectibility.
>
> All errors (new ones prefixed by >>):
>
> In file included from arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi:1:0,
> from arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts:5:
>>> arch/arm64/boot/dts/nvidia/tegra186.dtsi:7:55: fatal error: dt-bindings/thermal/tegra186-bpmp-thermal.h: No such file or directory
> #include <dt-bindings/thermal/tegra186-bpmp-thermal.h>
> ^
> compilation terminated.
>
> vim +7 arch/arm64/boot/dts/nvidia/tegra186.dtsi
>
> > 7 #include <dt-bindings/thermal/tegra186-bpmp-thermal.h>
> 8
>
> ---
> 0-DAY kernel test infrastructure Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all Intel Corporation
>

2017-08-11 02:58:11

by Zhang, Rui

[permalink] [raw]
Subject: Re: [PATCH v2 5/5] thermal: Add Tegra BPMP thermal sensor driver

On Mon, 2017-07-24 at 19:29 +0300, Mikko Perttunen wrote:
> On Tegra186, the BPMP (Boot and Power Management Processor) exposes
> an
> interface to thermal sensors on the system-on-chip. This driver
> implements access to the interface. It supports reading the
> temperature, setting trip points and receiving notification of a
> tripped trip point.
>
> Signed-off-by: Mikko Perttunen <[email protected]>

Wei Ni,

what do you think of this patch?

thanks,
rui
> ---
> v2:
> - don't allocate space for disabled zones
> - allow compilation with COMPILE_TEST
>
>  drivers/thermal/Makefile             |   2 +-
>  drivers/thermal/tegra/Kconfig        |   7 +
>  drivers/thermal/tegra/Makefile       |   3 +-
>  drivers/thermal/tegra/bpmp-thermal.c | 263
> +++++++++++++++++++++++++++++++++++
>  4 files changed, 273 insertions(+), 2 deletions(-)
>  create mode 100644 drivers/thermal/tegra/bpmp-thermal.c
>
> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
> index 094d7039981c..c03dccdba7b8 100644
> --- a/drivers/thermal/Makefile
> +++ b/drivers/thermal/Makefile
> @@ -54,7 +54,7 @@ obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) +=
> intel_bxt_pmic_thermal.o
>  obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
>  obj-$(CONFIG_ST_THERMAL) += st/
>  obj-$(CONFIG_QCOM_TSENS) += qcom/
> -obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
> +obj-y += tegra/
>  obj-$(CONFIG_HISI_THERMAL)     += hisi_thermal.o
>  obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
>  obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
> diff --git a/drivers/thermal/tegra/Kconfig
> b/drivers/thermal/tegra/Kconfig
> index cec586ec7e4b..f8740f7852e3 100644
> --- a/drivers/thermal/tegra/Kconfig
> +++ b/drivers/thermal/tegra/Kconfig
> @@ -10,4 +10,11 @@ config TEGRA_SOCTHERM
>     zones to manage temperatures. This option is also required
> for the
>     emergency thermal reset (thermtrip) feature to function.
>  
> +config TEGRA_BPMP_THERMAL
> + tristate "Tegra BPMP thermal sensing"
> + depends on TEGRA_BPMP || COMPILE_TEST
> + help
> +  Enable this option for support for sensing system
> temperature of NVIDIA
> +  Tegra systems-on-chip with the BPMP coprocessor (Tegra186).
> +
>  endmenu
> diff --git a/drivers/thermal/tegra/Makefile
> b/drivers/thermal/tegra/Makefile
> index 1ce1af2cf0f5..757abcd1feaf 100644
> --- a/drivers/thermal/tegra/Makefile
> +++ b/drivers/thermal/tegra/Makefile
> @@ -1,4 +1,5 @@
> -obj-$(CONFIG_TEGRA_SOCTHERM) += tegra-soctherm.o
> +obj-$(CONFIG_TEGRA_SOCTHERM) += tegra-soctherm.o
> +obj-$(CONFIG_TEGRA_BPMP_THERMAL) += bpmp-thermal.o
>  
>  tegra-soctherm-y := soctherm.o
> soctherm-fuse.o
>  tegra-soctherm-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124-
> soctherm.o
> diff --git a/drivers/thermal/tegra/bpmp-thermal.c
> b/drivers/thermal/tegra/bpmp-thermal.c
> new file mode 100644
> index 000000000000..b0980dbca3b3
> --- /dev/null
> +++ b/drivers/thermal/tegra/bpmp-thermal.c
> @@ -0,0 +1,263 @@
> +/*
> + * Copyright (c) 2015-2017, NVIDIA CORPORATION.  All rights
> reserved.
> + *
> + * Author:
> + * Mikko Perttunen <[email protected]>
> + * Aapo Vienamo <[email protected]>
> + *
> + * This software is licensed under the terms of the GNU General
> Public
> + * License version 2, as published by the Free Software Foundation,
> and
> + * may be copied, distributed, and modified under those terms.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include <linux/err.h>
> +#include <linux/module.h>
> +#include <linux/platform_device.h>
> +#include <linux/thermal.h>
> +#include <linux/workqueue.h>
> +
> +#include <soc/tegra/bpmp.h>
> +#include <soc/tegra/bpmp-abi.h>
> +
> +struct tegra_bpmp_thermal_zone {
> + struct tegra_bpmp_thermal *tegra;
> + struct thermal_zone_device *tzd;
> + struct work_struct tz_device_update_work;
> + unsigned int idx;
> +};
> +
> +struct tegra_bpmp_thermal {
> + struct device *dev;
> + struct tegra_bpmp *bpmp;
> + unsigned int num_zones;
> + struct tegra_bpmp_thermal_zone **zones;
> +};
> +
> +static int tegra_bpmp_thermal_get_temp(void *data, int *out_temp)
> +{
> + struct tegra_bpmp_thermal_zone *zone = data;
> + struct mrq_thermal_host_to_bpmp_request req;
> + union mrq_thermal_bpmp_to_host_response reply;
> + struct tegra_bpmp_message msg;
> + int err;
> +
> + memset(&req, 0, sizeof(req));
> + req.type = CMD_THERMAL_GET_TEMP;
> + req.get_temp.zone = zone->idx;
> +
> + memset(&msg, 0, sizeof(msg));
> + msg.mrq = MRQ_THERMAL;
> + msg.tx.data = &req;
> + msg.tx.size = sizeof(req);
> + msg.rx.data = &reply;
> + msg.rx.size = sizeof(reply);
> +
> + err = tegra_bpmp_transfer(zone->tegra->bpmp, &msg);
> + if (err)
> + return err;
> +
> + *out_temp = reply.get_temp.temp;
> +
> + return 0;
> +}
> +
> +static int tegra_bpmp_thermal_set_trips(void *data, int low, int
> high)
> +{
> + struct tegra_bpmp_thermal_zone *zone = data;
> + struct mrq_thermal_host_to_bpmp_request req;
> + struct tegra_bpmp_message msg;
> +
> + memset(&req, 0, sizeof(req));
> + req.type = CMD_THERMAL_SET_TRIP;
> + req.set_trip.zone = zone->idx;
> + req.set_trip.enabled = true;
> + req.set_trip.low = low;
> + req.set_trip.high = high;
> +
> + memset(&msg, 0, sizeof(msg));
> + msg.mrq = MRQ_THERMAL;
> + msg.tx.data = &req;
> + msg.tx.size = sizeof(req);
> +
> + return tegra_bpmp_transfer(zone->tegra->bpmp, &msg);
> +}
> +
> +static void tz_device_update_work_fn(struct work_struct *work)
> +{
> + struct tegra_bpmp_thermal_zone *zone;
> +
> + zone = container_of(work, struct tegra_bpmp_thermal_zone,
> +     tz_device_update_work);
> +
> + thermal_zone_device_update(zone->tzd,
> THERMAL_TRIP_VIOLATED);
> +}
> +
> +static void bpmp_mrq_thermal(unsigned int mrq, struct
> tegra_bpmp_channel *ch,
> +      void *data)
> +{
> + struct mrq_thermal_bpmp_to_host_request *req;
> + struct tegra_bpmp_thermal *tegra = data;
> + int i;
> +
> + req = (struct mrq_thermal_bpmp_to_host_request *)ch->ib-
> >data;
> +
> + if (req->type != CMD_THERMAL_HOST_TRIP_REACHED) {
> + dev_err(tegra->dev, "%s: invalid request type:
> %d\n",
> + __func__, req->type);
> + tegra_bpmp_mrq_return(ch, -EINVAL, NULL, 0);
> + return;
> + }
> +
> + for (i = 0; i < tegra->num_zones; ++i) {
> + if (tegra->zones[i]->idx != req-
> >host_trip_reached.zone)
> + continue;
> +
> + schedule_work(&tegra->zones[i]-
> >tz_device_update_work);
> + tegra_bpmp_mrq_return(ch, 0, NULL, 0);
> + return;
> + }
> +
> + dev_err(tegra->dev, "%s: invalid thermal zone: %d\n",
> __func__,
> + req->host_trip_reached.zone);
> + tegra_bpmp_mrq_return(ch, -EINVAL, NULL, 0);
> +}
> +
> +static int tegra_bpmp_thermal_get_num_zones(struct tegra_bpmp *bpmp,
> +     int *num_zones)
> +{
> + struct mrq_thermal_host_to_bpmp_request req;
> + union mrq_thermal_bpmp_to_host_response reply;
> + struct tegra_bpmp_message msg;
> + int err;
> +
> + memset(&req, 0, sizeof(req));
> + req.type = CMD_THERMAL_GET_NUM_ZONES;
> +
> + memset(&msg, 0, sizeof(msg));
> + msg.mrq = MRQ_THERMAL;
> + msg.tx.data = &req;
> + msg.tx.size = sizeof(req);
> + msg.rx.data = &reply;
> + msg.rx.size = sizeof(reply);
> +
> + err = tegra_bpmp_transfer(bpmp, &msg);
> + if (err)
> + return err;
> +
> + *num_zones = reply.get_num_zones.num;
> +
> + return 0;
> +}
> +
> +static const struct thermal_zone_of_device_ops
> tegra_bpmp_of_thermal_ops = {
> + .get_temp = tegra_bpmp_thermal_get_temp,
> + .set_trips = tegra_bpmp_thermal_set_trips,
> +};
> +
> +static int tegra_bpmp_thermal_probe(struct platform_device *pdev)
> +{
> + struct tegra_bpmp *bpmp = dev_get_drvdata(pdev->dev.parent);
> + struct tegra_bpmp_thermal *tegra;
> + struct thermal_zone_device *tzd;
> + unsigned int i, max_num_zones;
> + int err;
> +
> + tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra),
> GFP_KERNEL);
> + if (!tegra)
> + return -ENOMEM;
> +
> + tegra->dev = &pdev->dev;
> + tegra->bpmp = bpmp;
> +
> + err = tegra_bpmp_thermal_get_num_zones(bpmp,
> &max_num_zones);
> + if (err) {
> + dev_err(&pdev->dev, "failed to get the number of
> zones: %d\n",
> + err);
> + return err;
> + }
> +
> + tegra->zones = devm_kcalloc(&pdev->dev, max_num_zones,
> +     sizeof(*tegra->zones),
> GFP_KERNEL);
> + if (!tegra->zones)
> + return -ENOMEM;
> +
> + for (i = 0; i < max_num_zones; ++i) {
> + struct tegra_bpmp_thermal_zone *zone;
> + int temp;
> +
> + zone = devm_kzalloc(&pdev->dev, sizeof(*zone),
> GFP_KERNEL);
> + if (!zone)
> + return -ENOMEM;
> +
> + zone->idx = i;
> + zone->tegra = tegra;
> +
> + err = tegra_bpmp_thermal_get_temp(zone, &temp);
> + if (err < 0) {
> + devm_kfree(&pdev->dev, zone);
> + continue;
> + }
> +
> + tzd = devm_thermal_zone_of_sensor_register(
> + &pdev->dev, i, zone,
> &tegra_bpmp_of_thermal_ops);
> + if (IS_ERR(tzd)) {
> + if (PTR_ERR(tzd) == -EPROBE_DEFER)
> + return -EPROBE_DEFER;
> + devm_kfree(&pdev->dev, zone);
> + continue;
> + }
> +
> + zone->tzd = tzd;
> + INIT_WORK(&zone->tz_device_update_work,
> +   tz_device_update_work_fn);
> +
> + tegra->zones[tegra->num_zones++] = zone;
> + }
> +
> + err = tegra_bpmp_request_mrq(bpmp, MRQ_THERMAL,
> bpmp_mrq_thermal,
> +      tegra);
> + if (err) {
> + dev_err(&pdev->dev, "failed to register mrq handler:
> %d\n",
> + err);
> + return err;
> + }
> +
> + platform_set_drvdata(pdev, tegra);
> +
> + return 0;
> +}
> +
> +static int tegra_bpmp_thermal_remove(struct platform_device *pdev)
> +{
> + struct tegra_bpmp_thermal *tegra =
> platform_get_drvdata(pdev);
> +
> + tegra_bpmp_free_mrq(tegra->bpmp, MRQ_THERMAL, tegra);
> +
> + return 0;
> +}
> +
> +static const struct of_device_id tegra_bpmp_thermal_of_match[] = {
> + { .compatible = "nvidia,tegra186-bpmp-thermal" },
> + { },
> +};
> +MODULE_DEVICE_TABLE(of, tegra_bpmp_thermal_of_match);
> +
> +static struct platform_driver tegra_bpmp_thermal_driver = {
> + .probe = tegra_bpmp_thermal_probe,
> + .remove = tegra_bpmp_thermal_remove,
> + .driver = {
> + .name = "tegra-bpmp-thermal",
> + .of_match_table = tegra_bpmp_thermal_of_match,
> + },
> +};
> +module_platform_driver(tegra_bpmp_thermal_driver);
> +
> +MODULE_AUTHOR("Mikko Perttunen <[email protected]>");
> +MODULE_DESCRIPTION("NVIDIA Tegra BPMP thermal sensor driver");
> +MODULE_LICENSE("GPL v2");

2017-08-21 02:45:59

by Wei Ni

[permalink] [raw]
Subject: Re: [PATCH v2 5/5] thermal: Add Tegra BPMP thermal sensor driver



On Friday, August 11, 2017 10:57 AM, Zhang Rui wrote:
> On Mon, 2017-07-24 at 19:29 +0300, Mikko Perttunen wrote:
>> On Tegra186, the BPMP (Boot and Power Management Processor) exposes
>> an
>> interface to thermal sensors on the system-on-chip. This driver
>> implements access to the interface. It supports reading the
>> temperature, setting trip points and receiving notification of a
>> tripped trip point.
>>
>> Signed-off-by: Mikko Perttunen <[email protected]>
>
> Wei Ni,
>
> what do you think of this patch?

Reviewed this patch, it looked fine to me.

>
> thanks,
> rui
>> ---
>> v2:
>> - don't allocate space for disabled zones
>> - allow compilation with COMPILE_TEST
>>
>> drivers/thermal/Makefile | 2 +-
>> drivers/thermal/tegra/Kconfig | 7 +
>> drivers/thermal/tegra/Makefile | 3 +-
>> drivers/thermal/tegra/bpmp-thermal.c | 263
>> +++++++++++++++++++++++++++++++++++
>> 4 files changed, 273 insertions(+), 2 deletions(-)
>> create mode 100644 drivers/thermal/tegra/bpmp-thermal.c
>>
>> diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
>> index 094d7039981c..c03dccdba7b8 100644
>> --- a/drivers/thermal/Makefile
>> +++ b/drivers/thermal/Makefile
>> @@ -54,7 +54,7 @@ obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) +=
>> intel_bxt_pmic_thermal.o
>> obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o
>> obj-$(CONFIG_ST_THERMAL) += st/
>> obj-$(CONFIG_QCOM_TSENS) += qcom/
>> -obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/
>> +obj-y += tegra/
>> obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
>> obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
>> obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o
>> diff --git a/drivers/thermal/tegra/Kconfig
>> b/drivers/thermal/tegra/Kconfig
>> index cec586ec7e4b..f8740f7852e3 100644
>> --- a/drivers/thermal/tegra/Kconfig
>> +++ b/drivers/thermal/tegra/Kconfig
>> @@ -10,4 +10,11 @@ config TEGRA_SOCTHERM
>> zones to manage temperatures. This option is also required
>> for the
>> emergency thermal reset (thermtrip) feature to function.
>>
>> +config TEGRA_BPMP_THERMAL
>> + tristate "Tegra BPMP thermal sensing"
>> + depends on TEGRA_BPMP || COMPILE_TEST
>> + help
>> + Enable this option for support for sensing system
>> temperature of NVIDIA
>> + Tegra systems-on-chip with the BPMP coprocessor (Tegra186).
>> +
>> endmenu
>> diff --git a/drivers/thermal/tegra/Makefile
>> b/drivers/thermal/tegra/Makefile
>> index 1ce1af2cf0f5..757abcd1feaf 100644
>> --- a/drivers/thermal/tegra/Makefile
>> +++ b/drivers/thermal/tegra/Makefile
>> @@ -1,4 +1,5 @@
>> -obj-$(CONFIG_TEGRA_SOCTHERM) += tegra-soctherm.o
>> +obj-$(CONFIG_TEGRA_SOCTHERM) += tegra-soctherm.o
>> +obj-$(CONFIG_TEGRA_BPMP_THERMAL) += bpmp-thermal.o
>>
>> tegra-soctherm-y := soctherm.o
>> soctherm-fuse.o
>> tegra-soctherm-$(CONFIG_ARCH_TEGRA_124_SOC) += tegra124-
>> soctherm.o
>> diff --git a/drivers/thermal/tegra/bpmp-thermal.c
>> b/drivers/thermal/tegra/bpmp-thermal.c
>> new file mode 100644
>> index 000000000000..b0980dbca3b3
>> --- /dev/null
>> +++ b/drivers/thermal/tegra/bpmp-thermal.c
>> @@ -0,0 +1,263 @@
>> +/*
>> + * Copyright (c) 2015-2017, NVIDIA CORPORATION. All rights
>> reserved.
>> + *
>> + * Author:
>> + * Mikko Perttunen <[email protected]>
>> + * Aapo Vienamo <[email protected]>
>> + *
>> + * This software is licensed under the terms of the GNU General
>> Public
>> + * License version 2, as published by the Free Software Foundation,
>> and
>> + * may be copied, distributed, and modified under those terms.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + */
>> +
>> +#include <linux/err.h>
>> +#include <linux/module.h>
>> +#include <linux/platform_device.h>
>> +#include <linux/thermal.h>
>> +#include <linux/workqueue.h>
>> +
>> +#include <soc/tegra/bpmp.h>
>> +#include <soc/tegra/bpmp-abi.h>
>> +
>> +struct tegra_bpmp_thermal_zone {
>> + struct tegra_bpmp_thermal *tegra;
>> + struct thermal_zone_device *tzd;
>> + struct work_struct tz_device_update_work;
>> + unsigned int idx;
>> +};
>> +
>> +struct tegra_bpmp_thermal {
>> + struct device *dev;
>> + struct tegra_bpmp *bpmp;
>> + unsigned int num_zones;
>> + struct tegra_bpmp_thermal_zone **zones;
>> +};
>> +
>> +static int tegra_bpmp_thermal_get_temp(void *data, int *out_temp)
>> +{
>> + struct tegra_bpmp_thermal_zone *zone = data;
>> + struct mrq_thermal_host_to_bpmp_request req;
>> + union mrq_thermal_bpmp_to_host_response reply;
>> + struct tegra_bpmp_message msg;
>> + int err;
>> +
>> + memset(&req, 0, sizeof(req));
>> + req.type = CMD_THERMAL_GET_TEMP;
>> + req.get_temp.zone = zone->idx;
>> +
>> + memset(&msg, 0, sizeof(msg));
>> + msg.mrq = MRQ_THERMAL;
>> + msg.tx.data = &req;
>> + msg.tx.size = sizeof(req);
>> + msg.rx.data = &reply;
>> + msg.rx.size = sizeof(reply);
>> +
>> + err = tegra_bpmp_transfer(zone->tegra->bpmp, &msg);
>> + if (err)
>> + return err;
>> +
>> + *out_temp = reply.get_temp.temp;
>> +
>> + return 0;
>> +}
>> +
>> +static int tegra_bpmp_thermal_set_trips(void *data, int low, int
>> high)
>> +{
>> + struct tegra_bpmp_thermal_zone *zone = data;
>> + struct mrq_thermal_host_to_bpmp_request req;
>> + struct tegra_bpmp_message msg;
>> +
>> + memset(&req, 0, sizeof(req));
>> + req.type = CMD_THERMAL_SET_TRIP;
>> + req.set_trip.zone = zone->idx;
>> + req.set_trip.enabled = true;
>> + req.set_trip.low = low;
>> + req.set_trip.high = high;
>> +
>> + memset(&msg, 0, sizeof(msg));
>> + msg.mrq = MRQ_THERMAL;
>> + msg.tx.data = &req;
>> + msg.tx.size = sizeof(req);
>> +
>> + return tegra_bpmp_transfer(zone->tegra->bpmp, &msg);
>> +}
>> +
>> +static void tz_device_update_work_fn(struct work_struct *work)
>> +{
>> + struct tegra_bpmp_thermal_zone *zone;
>> +
>> + zone = container_of(work, struct tegra_bpmp_thermal_zone,
>> + tz_device_update_work);
>> +
>> + thermal_zone_device_update(zone->tzd,
>> THERMAL_TRIP_VIOLATED);
>> +}
>> +
>> +static void bpmp_mrq_thermal(unsigned int mrq, struct
>> tegra_bpmp_channel *ch,
>> + void *data)
>> +{
>> + struct mrq_thermal_bpmp_to_host_request *req;
>> + struct tegra_bpmp_thermal *tegra = data;
>> + int i;
>> +
>> + req = (struct mrq_thermal_bpmp_to_host_request *)ch->ib-
>>> data;
>> +
>> + if (req->type != CMD_THERMAL_HOST_TRIP_REACHED) {
>> + dev_err(tegra->dev, "%s: invalid request type:
>> %d\n",
>> + __func__, req->type);
>> + tegra_bpmp_mrq_return(ch, -EINVAL, NULL, 0);
>> + return;
>> + }
>> +
>> + for (i = 0; i < tegra->num_zones; ++i) {
>> + if (tegra->zones[i]->idx != req-
>>> host_trip_reached.zone)
>> + continue;
>> +
>> + schedule_work(&tegra->zones[i]-
>>> tz_device_update_work);
>> + tegra_bpmp_mrq_return(ch, 0, NULL, 0);
>> + return;
>> + }
>> +
>> + dev_err(tegra->dev, "%s: invalid thermal zone: %d\n",
>> __func__,
>> + req->host_trip_reached.zone);
>> + tegra_bpmp_mrq_return(ch, -EINVAL, NULL, 0);
>> +}
>> +
>> +static int tegra_bpmp_thermal_get_num_zones(struct tegra_bpmp *bpmp,
>> + int *num_zones)
>> +{
>> + struct mrq_thermal_host_to_bpmp_request req;
>> + union mrq_thermal_bpmp_to_host_response reply;
>> + struct tegra_bpmp_message msg;
>> + int err;
>> +
>> + memset(&req, 0, sizeof(req));
>> + req.type = CMD_THERMAL_GET_NUM_ZONES;
>> +
>> + memset(&msg, 0, sizeof(msg));
>> + msg.mrq = MRQ_THERMAL;
>> + msg.tx.data = &req;
>> + msg.tx.size = sizeof(req);
>> + msg.rx.data = &reply;
>> + msg.rx.size = sizeof(reply);
>> +
>> + err = tegra_bpmp_transfer(bpmp, &msg);
>> + if (err)
>> + return err;
>> +
>> + *num_zones = reply.get_num_zones.num;
>> +
>> + return 0;
>> +}
>> +
>> +static const struct thermal_zone_of_device_ops
>> tegra_bpmp_of_thermal_ops = {
>> + .get_temp = tegra_bpmp_thermal_get_temp,
>> + .set_trips = tegra_bpmp_thermal_set_trips,
>> +};
>> +
>> +static int tegra_bpmp_thermal_probe(struct platform_device *pdev)
>> +{
>> + struct tegra_bpmp *bpmp = dev_get_drvdata(pdev->dev.parent);
>> + struct tegra_bpmp_thermal *tegra;
>> + struct thermal_zone_device *tzd;
>> + unsigned int i, max_num_zones;
>> + int err;
>> +
>> + tegra = devm_kzalloc(&pdev->dev, sizeof(*tegra),
>> GFP_KERNEL);
>> + if (!tegra)
>> + return -ENOMEM;
>> +
>> + tegra->dev = &pdev->dev;
>> + tegra->bpmp = bpmp;
>> +
>> + err = tegra_bpmp_thermal_get_num_zones(bpmp,
>> &max_num_zones);
>> + if (err) {
>> + dev_err(&pdev->dev, "failed to get the number of
>> zones: %d\n",
>> + err);
>> + return err;
>> + }
>> +
>> + tegra->zones = devm_kcalloc(&pdev->dev, max_num_zones,
>> + sizeof(*tegra->zones),
>> GFP_KERNEL);
>> + if (!tegra->zones)
>> + return -ENOMEM;
>> +
>> + for (i = 0; i < max_num_zones; ++i) {
>> + struct tegra_bpmp_thermal_zone *zone;
>> + int temp;
>> +
>> + zone = devm_kzalloc(&pdev->dev, sizeof(*zone),
>> GFP_KERNEL);
>> + if (!zone)
>> + return -ENOMEM;
>> +
>> + zone->idx = i;
>> + zone->tegra = tegra;
>> +
>> + err = tegra_bpmp_thermal_get_temp(zone, &temp);
>> + if (err < 0) {
>> + devm_kfree(&pdev->dev, zone);
>> + continue;
>> + }
>> +
>> + tzd = devm_thermal_zone_of_sensor_register(
>> + &pdev->dev, i, zone,
>> &tegra_bpmp_of_thermal_ops);
>> + if (IS_ERR(tzd)) {
>> + if (PTR_ERR(tzd) == -EPROBE_DEFER)
>> + return -EPROBE_DEFER;
>> + devm_kfree(&pdev->dev, zone);
>> + continue;
>> + }
>> +
>> + zone->tzd = tzd;
>> + INIT_WORK(&zone->tz_device_update_work,
>> + tz_device_update_work_fn);
>> +
>> + tegra->zones[tegra->num_zones++] = zone;
>> + }
>> +
>> + err = tegra_bpmp_request_mrq(bpmp, MRQ_THERMAL,
>> bpmp_mrq_thermal,
>> + tegra);
>> + if (err) {
>> + dev_err(&pdev->dev, "failed to register mrq handler:
>> %d\n",
>> + err);
>> + return err;
>> + }
>> +
>> + platform_set_drvdata(pdev, tegra);
>> +
>> + return 0;
>> +}
>> +
>> +static int tegra_bpmp_thermal_remove(struct platform_device *pdev)
>> +{
>> + struct tegra_bpmp_thermal *tegra =
>> platform_get_drvdata(pdev);
>> +
>> + tegra_bpmp_free_mrq(tegra->bpmp, MRQ_THERMAL, tegra);
>> +
>> + return 0;
>> +}
>> +
>> +static const struct of_device_id tegra_bpmp_thermal_of_match[] = {
>> + { .compatible = "nvidia,tegra186-bpmp-thermal" },
>> + { },
>> +};
>> +MODULE_DEVICE_TABLE(of, tegra_bpmp_thermal_of_match);
>> +
>> +static struct platform_driver tegra_bpmp_thermal_driver = {
>> + .probe = tegra_bpmp_thermal_probe,
>> + .remove = tegra_bpmp_thermal_remove,
>> + .driver = {
>> + .name = "tegra-bpmp-thermal",
>> + .of_match_table = tegra_bpmp_thermal_of_match,
>> + },
>> +};
>> +module_platform_driver(tegra_bpmp_thermal_driver);
>> +
>> +MODULE_AUTHOR("Mikko Perttunen <[email protected]>");
>> +MODULE_DESCRIPTION("NVIDIA Tegra BPMP thermal sensor driver");
>> +MODULE_LICENSE("GPL v2");
>
> _______________________________________________
> linux-arm-kernel mailing list
> [email protected]
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

2017-08-31 12:45:12

by Thierry Reding

[permalink] [raw]
Subject: Re: [PATCH v2 5/5] thermal: Add Tegra BPMP thermal sensor driver

On Mon, Aug 21, 2017 at 10:40:44AM +0800, Wei Ni wrote:
>
>
> On Friday, August 11, 2017 10:57 AM, Zhang Rui wrote:
> > On Mon, 2017-07-24 at 19:29 +0300, Mikko Perttunen wrote:
> >> On Tegra186, the BPMP (Boot and Power Management Processor) exposes
> >> an
> >> interface to thermal sensors on the system-on-chip. This driver
> >> implements access to the interface. It supports reading the
> >> temperature, setting trip points and receiving notification of a
> >> tripped trip point.
> >>
> >> Signed-off-by: Mikko Perttunen <[email protected]>
> >
> > Wei Ni,
> >
> > what do you think of this patch?
>
> Reviewed this patch, it looked fine to me.

Hi Zhang,

given the build-time dependencies, how about if I take this into the
Tegra tree with an Acked-by from you? I can provide a stable branch with
the dependencies included if you want to pull it into your tree in order
to resolve dependencies.

Thierry


Attachments:
(No filename) (923.00 B)
signature.asc (833.00 B)
Download all attachments

2017-09-01 01:23:54

by Zhang, Rui

[permalink] [raw]
Subject: Re: [PATCH v2 5/5] thermal: Add Tegra BPMP thermal sensor driver

On Thu, 2017-08-31 at 14:45 +0200, Thierry Reding wrote:
> On Mon, Aug 21, 2017 at 10:40:44AM +0800, Wei Ni wrote:
> >
> >
> >
> > On Friday, August 11, 2017 10:57 AM, Zhang Rui wrote:
> > >
> > > On Mon, 2017-07-24 at 19:29 +0300, Mikko Perttunen wrote:
> > > >
> > > > On Tegra186, the BPMP (Boot and Power Management Processor)
> > > > exposes
> > > > an
> > > > interface to thermal sensors on the system-on-chip. This driver
> > > > implements access to the interface. It supports reading the
> > > > temperature, setting trip points and receiving notification of
> > > > a
> > > > tripped trip point.
> > > >
> > > > Signed-off-by: Mikko Perttunen <[email protected]>

Acked-by: Zhang Rui <[email protected]>
for this patch and patch 1/5.


> > > Wei Ni,
> > >
> > > what do you think of this patch?
> > Reviewed this patch, it looked fine to me.
> Hi Zhang,
>
> given the build-time dependencies, how about if I take this into the
> Tegra tree with an Acked-by from you?

Sounds okay to me. Done. :)

thanks,
rui

> I can provide a stable branch with
> the dependencies included if you want to pull it into your tree in
> order
> to resolve dependencies.
>
> Thierry