Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6a7202fc authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "defconfig: msm: enable thermal efuse driver for kona iot"

parents 34bd57b5 97dff8ed
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -396,6 +396,7 @@ CONFIG_QTI_QMI_COOLING_DEVICE=y
CONFIG_QTI_THERMAL_LIMITS_DCVS=y
CONFIG_QTI_THERMAL_LIMITS_DCVS=y
CONFIG_QTI_CPU_ISOLATE_COOLING_DEVICE=y
CONFIG_QTI_CPU_ISOLATE_COOLING_DEVICE=y
CONFIG_QTI_LIMITS_ISENSE_CDSP=y
CONFIG_QTI_LIMITS_ISENSE_CDSP=y
CONFIG_QTI_THERMAL_QFPROM=y
CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR=y
+1 −0
Original line number Original line Diff line number Diff line
@@ -412,6 +412,7 @@ CONFIG_QTI_QMI_COOLING_DEVICE=y
CONFIG_QTI_THERMAL_LIMITS_DCVS=y
CONFIG_QTI_THERMAL_LIMITS_DCVS=y
CONFIG_QTI_CPU_ISOLATE_COOLING_DEVICE=y
CONFIG_QTI_CPU_ISOLATE_COOLING_DEVICE=y
CONFIG_QTI_LIMITS_ISENSE_CDSP=y
CONFIG_QTI_LIMITS_ISENSE_CDSP=y
CONFIG_QTI_THERMAL_QFPROM=y
CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_I2C_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_MFD_SPMI_PMIC=y
CONFIG_REGULATOR=y
CONFIG_REGULATOR=y
+11 −0
Original line number Original line Diff line number Diff line
@@ -151,3 +151,14 @@ config QTI_CX_IPEAK_COOLING_DEVICE
	  on the CX rail.
	  on the CX rail.


	  If you want this support, you should say Y here.
	  If you want this support, you should say Y here.

config QTI_THERMAL_QFPROM
	tristate "Qualcomm Technologies Inc. thermal QFPROM driver"
	depends on THERMAL
	depends on QCOM_QFPROM
	help
	  This driver enables or disables pre-configured thermal zones
	  selectively at runtime based on QFPROM nvmem cell bit value is
	  set or not. It supports to check multiple nvmem cell value for
	  multiple condtion. In that case, if any of the nvmem-cell condition
	  fails, driver just exits with default enabled thermal zones.
+1 −0
Original line number Original line Diff line number Diff line
@@ -14,3 +14,4 @@ obj-$(CONFIG_QTI_CPU_ISOLATE_COOLING_DEVICE) += cpu_isolate.o
obj-$(CONFIG_QTI_LMH_CPU_VDD_COOLING_DEVICE) += lmh_cpu_vdd_cdev.o
obj-$(CONFIG_QTI_LMH_CPU_VDD_COOLING_DEVICE) += lmh_cpu_vdd_cdev.o
obj-$(CONFIG_QTI_LIMITS_ISENSE_CDSP) += msm_isense_cdsp.o
obj-$(CONFIG_QTI_LIMITS_ISENSE_CDSP) += msm_isense_cdsp.o
obj-$(CONFIG_QTI_CX_IPEAK_COOLING_DEVICE) += cx_ipeak_cdev.o
obj-$(CONFIG_QTI_CX_IPEAK_COOLING_DEVICE) += cx_ipeak_cdev.o
obj-$(CONFIG_QTI_THERMAL_QFPROM) += qti_thermal_qfprom.o
+173 −0
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
 */

#define pr_fmt(fmt) "%s:%s " fmt, KBUILD_MODNAME, __func__

#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/nvmem-consumer.h>
#include <linux/thermal.h>

#include "../thermal_core.h"

static int thermal_qfprom_read(struct platform_device *pdev,
			const char *cname, unsigned int *efuse_val)
{
	struct nvmem_cell *cell;
	size_t len;
	char *buf;

	cell = nvmem_cell_get(&pdev->dev, cname);
	if (IS_ERR(cell)) {
		dev_err(&pdev->dev, "failed to get nvmem cell %s\n", cname);
		return -EINVAL;
	}

	buf = nvmem_cell_read(cell, &len);
	nvmem_cell_put(cell);
	if (IS_ERR_OR_NULL(buf)) {
		dev_err(&pdev->dev, "failed to read nvmem cell %s\n", cname);
		return -EINVAL;
	}

	if (len <= 0 || len > sizeof(u32)) {
		dev_err(&pdev->dev, "nvmem cell length out of range:%d\n", len);
		kfree(buf);
		return -EINVAL;
	}
	memcpy(efuse_val, buf, min(len, sizeof(*efuse_val)));
	kfree(buf);

	return 0;
}

static int thermal_zone_set_mode(struct platform_device *pdev,
			enum thermal_device_mode mode)
{
	const char *name;
	struct property *prop = NULL;

	of_property_for_each_string(pdev->dev.of_node,
		mode == THERMAL_DEVICE_ENABLED ?
		"qcom,thermal-zone-enable-list" :
		"qcom,thermal-zone-disable-list", prop, name) {
		struct thermal_zone_device *zone;
		struct thermal_instance *pos;

		zone = thermal_zone_get_zone_by_name(name);
		if (IS_ERR(zone)) {
			dev_err(&pdev->dev,
				"could not find %s thermal zone\n", name);
			continue;
		}

		if (!(zone->ops && zone->ops->set_mode)) {
			dev_err(&pdev->dev,
				"thermal zone ops is not supported for %s\n",
				name);
			continue;
		}

		zone->ops->set_mode(zone, mode);
		if (mode == THERMAL_DEVICE_DISABLED) {
			/* Clear thermal zone device */
			mutex_lock(&zone->lock);
			zone->temperature = THERMAL_TEMP_INVALID;
			zone->passive = 0;
			list_for_each_entry(pos, &zone->thermal_instances,
				tz_node) {
				pos->initialized = false;
				pos->target = THERMAL_NO_TARGET;
				mutex_lock(&pos->cdev->lock);
				pos->cdev->updated = false;
				mutex_unlock(&pos->cdev->lock);
				thermal_cdev_update(pos->cdev);
			}
			mutex_unlock(&zone->lock);
		}
		dev_dbg(&pdev->dev, "thermal zone %s is %s\n", name,
			mode == THERMAL_DEVICE_ENABLED ?
			"enabled" : "disabled");
	}

	return 0;
}

static void update_thermal_zones(struct platform_device *pdev)
{
	thermal_zone_set_mode(pdev, THERMAL_DEVICE_ENABLED);
	thermal_zone_set_mode(pdev, THERMAL_DEVICE_DISABLED);
}

static int thermal_qfprom_probe(struct platform_device *pdev)
{
	int err = 0;
	const char *name;
	struct property *prop = NULL;
	u8 efuse_pass_cnt = 0;

	of_property_for_each_string(pdev->dev.of_node,
		"nvmem-cell-names", prop, name) {
		u32 efuse_val = 0, efuse_match_val = 0;

		err = thermal_qfprom_read(pdev, name, &efuse_val);
		if (err)
			return err;

		err = of_property_read_u32_index(pdev->dev.of_node,
			"qcom,thermal-qfprom-bit-values", efuse_pass_cnt,
			&efuse_match_val);
		if (err) {
			dev_err(&pdev->dev,
				"Invalid qfprom bit value for index %d\n",
				efuse_pass_cnt);
			return err;
		}

		dev_dbg(&pdev->dev, "efuse[%s] val:0x%x match val[%d]:0x%x\n",
				name, efuse_val, efuse_pass_cnt,
				efuse_match_val);

		/* if any of efuse condition fails, just exit */
		if (efuse_val != efuse_match_val)
			return 0;

		efuse_pass_cnt++;
	}

	if (efuse_pass_cnt)
		update_thermal_zones(pdev);

	return err;
}

static const struct of_device_id thermal_qfprom_match[] = {
	{ .compatible = "qcom,thermal-qfprom-device", },
	{},
};

static struct platform_driver thermal_qfprom_driver = {
	.probe = thermal_qfprom_probe,
	.driver = {
		.name = KBUILD_MODNAME,
		.of_match_table = thermal_qfprom_match,
	},
};

int __init thermal_qfprom_init(void)
{
	int err;

	err = platform_driver_register(&thermal_qfprom_driver);
	if (err)
		pr_err("Failed to register thermal qfprom platform driver:%d\n",
			err);
	return err;
}

late_initcall(thermal_qfprom_init);