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

Commit 33ba9737 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "thermal: tsens: Add MTC and sysfs support for sensors"

parents abea5c0b d083b230
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -61,4 +61,4 @@ obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o
obj-$(CONFIG_GENERIC_ADC_THERMAL)	+= thermal-generic-adc.o
obj-$(CONFIG_ZX2967_THERMAL)	+= zx2967_thermal.o
obj-$(CONFIG_UNIPHIER_THERMAL)	+= uniphier_thermal.o
obj-$(CONFIG_THERMAL_TSENS)	+= msm-tsens.o tsens2xxx.o tsens-dbg.o
obj-$(CONFIG_THERMAL_TSENS)	+= msm-tsens.o tsens2xxx.o tsens-dbg.o tsens-mtc.o
+175 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -13,7 +13,9 @@

#include <asm/arch_timer.h>
#include <linux/sched/clock.h>
#include <linux/platform_device.h>
#include "tsens.h"
#include "tsens-mtc.h"

/* debug defines */
#define	TSENS_DBG_BUS_ID_0			0
@@ -43,6 +45,177 @@ struct tsens_dbg_func {
	int (*dbg_func)(struct tsens_device *, u32, u32, int *);
};

static ssize_t
zonemask_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	struct tsens_device *tmdev = NULL;

	tmdev = tsens_controller_is_present();
	if (!tmdev) {
		pr_err("No TSENS controller present\n");
		return -EPROBE_DEFER;
	}

	return snprintf(buf, PAGE_SIZE,
		"Zone =%d th1=%d th2=%d\n", tmdev->mtcsys.zone_mtc,
				tmdev->mtcsys.th1, tmdev->mtcsys.th2);
}

static ssize_t
zonemask_store(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{
	int ret;
	struct tsens_device *tmdev = NULL;

	tmdev = tsens_controller_is_present();
	if (!tmdev) {
		pr_err("No TSENS controller present\n");
		return -EPROBE_DEFER;
	}

	ret = sscanf(buf, "%d %d %d", &tmdev->mtcsys.zone_mtc,
				&tmdev->mtcsys.th1, &tmdev->mtcsys.th2);

	if (ret != TSENS_ZONEMASK_PARAMS) {
		pr_err("Invalid command line arguments\n");
		count = -EINVAL;
	} else {
		pr_debug("store zone_mtc=%d th1=%d th2=%d\n",
				tmdev->mtcsys.zone_mtc,
				tmdev->mtcsys.th1, tmdev->mtcsys.th2);
		ret = tsens_set_mtc_zone_sw_mask(tmdev->mtcsys.zone_mtc,
					tmdev->mtcsys.th1, tmdev->mtcsys.th2);
		if (ret < 0) {
			pr_err("Invalid command line arguments\n");
			count = -EINVAL;
		}
	}

	return count;
}

static ssize_t
zonelog_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	int ret, zlog[TSENS_MTC_ZONE_LOG_SIZE];
	struct tsens_device *tmdev = NULL;

	tmdev = tsens_controller_is_present();
	if (!tmdev) {
		pr_err("No TSENS controller present\n");
		return -EPROBE_DEFER;
	}

	ret = tsens_get_mtc_zone_log(tmdev->mtcsys.zone_log, zlog);
	if (ret < 0) {
		pr_err("Invalid command line arguments\n");
		return -EINVAL;
	}

	return snprintf(buf, PAGE_SIZE,
		"Log[0]=%d\nLog[1]=%d\nLog[2]=%d\nLog[3]=%d\nLog[4]=%d\nLog[5]=%d\n",
			zlog[0], zlog[1], zlog[2], zlog[3], zlog[4], zlog[5]);
}

static ssize_t
zonelog_store(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{
	int ret;
	struct tsens_device *tmdev = NULL;

	tmdev = tsens_controller_is_present();
	if (!tmdev) {
		pr_err("No TSENS controller present\n");
		return -EPROBE_DEFER;
	}

	ret = kstrtou32(buf, 0, &tmdev->mtcsys.zone_log);
	if (ret < 0) {
		pr_err("Invalid command line arguments\n");
		return -EINVAL;
	}

	return count;
}

static ssize_t
zonehist_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	int ret, zhist[TSENS_MTC_ZONE_HISTORY_SIZE];
	struct tsens_device *tmdev = NULL;

	tmdev = tsens_controller_is_present();
	if (!tmdev) {
		pr_err("No TSENS controller present\n");
		return -EPROBE_DEFER;
	}

	ret = tsens_get_mtc_zone_history(tmdev->mtcsys.zone_hist, zhist);
	if (ret < 0) {
		pr_err("Invalid command line arguments\n");
		return -EINVAL;
	}

	return snprintf(buf, PAGE_SIZE,
		"Cool = %d\nYellow = %d\nRed = %d\n",
			zhist[0], zhist[1], zhist[2]);
}

static ssize_t
zonehist_store(struct device *dev, struct device_attribute *attr,
		const char *buf, size_t count)
{
	int ret;
	struct tsens_device *tmdev = NULL;

	tmdev = tsens_controller_is_present();
	if (!tmdev) {
		pr_err("No TSENS controller present\n");
		return -EPROBE_DEFER;
	}

	ret = kstrtou32(buf, 0, &tmdev->mtcsys.zone_hist);
	if (ret < 0) {
		pr_err("Invalid command line arguments\n");
		return -EINVAL;
	}

	return count;
}

static struct device_attribute tsens_mtc_dev_attr[] = {
	__ATTR(zonemask, 0644, zonemask_show, zonemask_store),
	__ATTR(zonelog, 0644, zonelog_show, zonelog_store),
	__ATTR(zonehist, 0644, zonehist_show, zonehist_store),
};

static int tsens_dbg_mtc_data(struct tsens_device *data,
					u32 id, u32 dbg_type, int *val)
{
	int result = 0, i;
	struct tsens_device *tmdev = NULL;
	struct device_attribute *attr_ptr = NULL;

	attr_ptr = tsens_mtc_dev_attr;
	tmdev = data;

	for (i = 0; i < ARRAY_SIZE(tsens_mtc_dev_attr); i++) {
		result = device_create_file(&tmdev->pdev->dev, &attr_ptr[i]);
		if (result < 0)
			goto error;
	}

	return result;

error:
	for (i--; i >= 0; i--)
		device_remove_file(&tmdev->pdev->dev, &attr_ptr[i]);

	return result;
}

static int tsens_dbg_log_temp_reads(struct tsens_device *data, u32 id,
					u32 dbg_type, int *temp)
{
@@ -207,6 +380,7 @@ static struct tsens_dbg_func dbg_arr[] = {
	[TSENS_DBG_LOG_INTERRUPT_TIMESTAMP] = {
			tsens_dbg_log_interrupt_timestamp},
	[TSENS_DBG_LOG_BUS_ID_DATA] = {tsens_dbg_log_bus_id_data},
	[TSENS_DBG_MTC_DATA] = {tsens_dbg_mtc_data},
};

int tsens2xxx_dbg(struct tsens_device *data, u32 id, u32 dbg_type, int *val)
+195 −0
Original line number Diff line number Diff line
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * 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 "tsens.h"
#include "tsens-mtc.h"

struct tsens_device *tsens_controller_is_present(void)
{
	struct tsens_device *tmdev_chip = NULL;

	if (list_empty(&tsens_device_list)) {
		pr_err("%s: TSENS controller not available\n", __func__);
		return tmdev_chip;
	}

	list_for_each_entry(tmdev_chip, &tsens_device_list, list)
		return tmdev_chip;

	return tmdev_chip;
}
EXPORT_SYMBOL(tsens_controller_is_present);

static int tsens_mtc_reset_history_counter(unsigned int zone)
{
	unsigned int reg_cntl, is_valid;
	void __iomem *sensor_addr;
	struct tsens_device *tmdev = NULL;

	if (zone > TSENS_NUM_MTC_ZONES_SUPPORT)
		return -EINVAL;

	tmdev = tsens_controller_is_present();
	if (!tmdev) {
		pr_err("No TSENS controller present\n");
		return -EPROBE_DEFER;
	}

	sensor_addr = TSENS_TM_MTC_ZONE0_SW_MASK_ADDR(tmdev->tsens_tm_addr);
	reg_cntl = readl_relaxed((sensor_addr +
		(zone * TSENS_SN_ADDR_OFFSET)));
	is_valid = (reg_cntl & TSENS_RESET_HISTORY_MASK)
				>> TSENS_RESET_HISTORY_SHIFT;
	if (!is_valid) {
		/*Enable the bit to reset counter*/
		writel_relaxed(reg_cntl | (1 << TSENS_RESET_HISTORY_SHIFT),
				(sensor_addr + (zone * TSENS_SN_ADDR_OFFSET)));
		reg_cntl = readl_relaxed((sensor_addr +
				(zone * TSENS_SN_ADDR_OFFSET)));
		pr_debug("tsens : zone =%d reg=%x\n", zone, reg_cntl);
	}

	/*Disable the bit to start counter*/
	writel_relaxed(reg_cntl & ~(1 << TSENS_RESET_HISTORY_SHIFT),
				(sensor_addr + (zone * TSENS_SN_ADDR_OFFSET)));
	reg_cntl = readl_relaxed((sensor_addr +
			(zone * TSENS_SN_ADDR_OFFSET)));
	pr_debug("tsens : zone =%d reg=%x\n", zone, reg_cntl);

	return 0;
}
EXPORT_SYMBOL(tsens_mtc_reset_history_counter);

int tsens_set_mtc_zone_sw_mask(unsigned int zone, unsigned int th1_enable,
				unsigned int th2_enable)
{
	unsigned int reg_cntl;
	void __iomem *sensor_addr;
	struct tsens_device *tmdev = NULL;

	if (zone > TSENS_NUM_MTC_ZONES_SUPPORT)
		return -EINVAL;

	tmdev = tsens_controller_is_present();
	if (!tmdev) {
		pr_err("No TSENS controller present\n");
		return -EPROBE_DEFER;
	}

	sensor_addr = TSENS_TM_MTC_ZONE0_SW_MASK_ADDR
					(tmdev->tsens_tm_addr);

	if (th1_enable && th2_enable)
		writel_relaxed(TSENS_MTC_IN_EFFECT,
				(sensor_addr +
				(zone * TSENS_SN_ADDR_OFFSET)));
	if (!th1_enable && !th2_enable)
		writel_relaxed(TSENS_MTC_DISABLE,
				(sensor_addr +
				(zone * TSENS_SN_ADDR_OFFSET)));
	if (th1_enable && !th2_enable)
		writel_relaxed(TSENS_TH1_MTC_IN_EFFECT,
				(sensor_addr +
				(zone * TSENS_SN_ADDR_OFFSET)));
	if (!th1_enable && th2_enable)
		writel_relaxed(TSENS_TH2_MTC_IN_EFFECT,
				(sensor_addr +
				(zone * TSENS_SN_ADDR_OFFSET)));
	reg_cntl = readl_relaxed((sensor_addr +
				(zone * TSENS_SN_ADDR_OFFSET)));
	pr_debug("tsens : zone =%d th1=%d th2=%d reg=%x\n",
		zone, th1_enable, th2_enable, reg_cntl);

	return 0;
}
EXPORT_SYMBOL(tsens_set_mtc_zone_sw_mask);

int tsens_get_mtc_zone_log(unsigned int zone, void *zone_log)
{
	unsigned int i, reg_cntl, is_valid, log[TSENS_MTC_ZONE_LOG_SIZE];
	int *zlog = (int *)zone_log;
	void __iomem *sensor_addr;
	struct tsens_device *tmdev = NULL;

	if (zone > TSENS_NUM_MTC_ZONES_SUPPORT)
		return -EINVAL;

	tmdev = tsens_controller_is_present();
	if (!tmdev) {
		pr_err("No TSENS controller present\n");
		return -EPROBE_DEFER;
	}

	sensor_addr = TSENS_TM_MTC_ZONE0_LOG(tmdev->tsens_tm_addr);

	reg_cntl = readl_relaxed((sensor_addr +
				(zone * TSENS_SN_ADDR_OFFSET)));
	is_valid = (reg_cntl & TSENS_LOGS_VALID_MASK)
				>> TSENS_LOGS_VALID_SHIFT;
	if (is_valid) {
		log[0] = (reg_cntl & TSENS_LOGS_LATEST_MASK);
		log[1] = (reg_cntl & TSENS_LOGS_LOG1_MASK)
				>> TSENS_LOGS_LOG1_SHIFT;
		log[2] = (reg_cntl & TSENS_LOGS_LOG2_MASK)
				>> TSENS_LOGS_LOG2_SHIFT;
		log[3] = (reg_cntl & TSENS_LOGS_LOG3_MASK)
				>> TSENS_LOGS_LOG3_SHIFT;
		log[4] = (reg_cntl & TSENS_LOGS_LOG4_MASK)
				>> TSENS_LOGS_LOG4_SHIFT;
		log[5] = (reg_cntl & TSENS_LOGS_LOG5_MASK)
				>> TSENS_LOGS_LOG5_SHIFT;
		for (i = 0; i < (TSENS_MTC_ZONE_LOG_SIZE); i++) {
			*(zlog+i) = log[i];
			pr_debug("Log[%d]=%d\n", i, log[i]);
		}
	} else {
		pr_debug("tsens: Valid bit disabled\n");
		return -EINVAL;
	}
	return 0;
}
EXPORT_SYMBOL(tsens_get_mtc_zone_log);

int tsens_get_mtc_zone_history(unsigned int zone, void *zone_hist)
{
	unsigned int i, reg_cntl, hist[TSENS_MTC_ZONE_HISTORY_SIZE];
	int *zhist = (int *)zone_hist;
	void __iomem *sensor_addr;
	struct tsens_device *tmdev = NULL;

	if (zone > TSENS_NUM_MTC_ZONES_SUPPORT)
		return -EINVAL;

	tmdev = tsens_controller_is_present();
	if (!tmdev) {
		pr_err("No TSENS controller present\n");
		return -EPROBE_DEFER;
	}

	sensor_addr = TSENS_TM_MTC_ZONE0_HISTORY(tmdev->tsens_tm_addr);
	reg_cntl = readl_relaxed((sensor_addr +
				(zone * TSENS_SN_ADDR_OFFSET)));

	hist[0] = (reg_cntl & TSENS_PS_COOL_CMD_MASK);
	hist[1] = (reg_cntl & TSENS_PS_YELLOW_CMD_MASK)
			>> TSENS_PS_YELLOW_CMD_SHIFT;
	hist[2] = (reg_cntl & TSENS_PS_RED_CMD_MASK)
			>> TSENS_PS_RED_CMD_SHIFT;
	for (i = 0; i < (TSENS_MTC_ZONE_HISTORY_SIZE); i++) {
		*(zhist+i) = hist[i];
		pr_debug("tsens : %d\n", hist[i]);
	}

	return 0;
}
EXPORT_SYMBOL(tsens_get_mtc_zone_history);
+59 −0
Original line number Diff line number Diff line
/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * 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.
 *
 */

#define TSENS_NUM_MTC_ZONES_SUPPORT 3
#define TSENS_TM_MTC_ZONE0_SW_MASK_ADDR(n)      ((n) + 0x140)
#define TSENS_TM_MTC_ZONE0_LOG(n)               ((n) + 0x150)
#define TSENS_TM_MTC_ZONE0_HISTORY(n)           ((n) + 0x160)
#define TSENS_SN_ADDR_OFFSET             0x4
#define TSENS_RESET_HISTORY_MASK        0x4
#define TSENS_ZONEMASK_PARAMS           3
#define TSENS_MTC_ZONE_LOG_SIZE         6
#define TSENS_MTC_ZONE_HISTORY_SIZE     3

#define TSENS_TH1_MTC_IN_EFFECT               BIT(0)
#define TSENS_TH2_MTC_IN_EFFECT               BIT(1)
#define TSENS_MTC_IN_EFFECT                     0x3
#define TSENS_MTC_DISABLE                       0x0

#define TSENS_LOGS_VALID_MASK      0x40000000
#define TSENS_LOGS_VALID_SHIFT     30
#define TSENS_LOGS_LATEST_MASK    0x0000001f
#define TSENS_LOGS_LOG1_MASK      0x000003e0
#define TSENS_LOGS_LOG2_MASK      0x00007c00
#define TSENS_LOGS_LOG3_MASK      0x000f8000
#define TSENS_LOGS_LOG4_MASK      0x01f00000
#define TSENS_LOGS_LOG5_MASK      0x3e000000
#define TSENS_LOGS_LOG1_SHIFT     5
#define TSENS_LOGS_LOG2_SHIFT     10
#define TSENS_LOGS_LOG3_SHIFT     15
#define TSENS_LOGS_LOG4_SHIFT     20
#define TSENS_LOGS_LOG5_SHIFT     25

#define TSENS_PS_RED_CMD_MASK   0x3ff00000
#define TSENS_PS_YELLOW_CMD_MASK        0x000ffc00
#define TSENS_PS_COOL_CMD_MASK  0x000003ff
#define TSENS_PS_YELLOW_CMD_SHIFT       0xa
#define TSENS_PS_RED_CMD_SHIFT  0x14

#define TSENS_RESET_HISTORY_SHIFT       2

#define TSENS_ZONEMASK_PARAMS           3
#define TSENS_MTC_ZONE_LOG_SIZE         6
#define TSENS_MTC_ZONE_HISTORY_SIZE     3

extern int tsens_get_mtc_zone_history(unsigned int zone, void *zone_hist);
extern struct tsens_device *tsens_controller_is_present(void);
extern int tsens_set_mtc_zone_sw_mask(unsigned int zone,
			unsigned int th1_enable, unsigned int th2_enable);
extern int tsens_get_mtc_zone_log(unsigned int zone, void *zone_log);
+13 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -32,6 +32,7 @@ enum tsens_dbg_type {
	TSENS_DBG_LOG_TEMP_READS,
	TSENS_DBG_LOG_INTERRUPT_TIMESTAMP,
	TSENS_DBG_LOG_BUS_ID_DATA,
	TSENS_DBG_MTC_DATA,
	TSENS_DBG_LOG_MAX
};

@@ -114,6 +115,15 @@ struct tsens_data {
	u32				cycle_compltn_monitor_mask;
	bool				wd_bark;
	u32				wd_bark_mask;
	bool				mtc;
};

struct tsens_mtc_sysfs {
	uint32_t	zone_log;
	int			zone_mtc;
	int			th1;
	int			th2;
	uint32_t	zone_hist;
};

struct tsens_device {
@@ -130,8 +140,10 @@ struct tsens_device {
	spinlock_t			tsens_upp_low_lock;
	const struct tsens_data		*ctrl_data;
	struct tsens_sensor		sensor[0];
	struct tsens_mtc_sysfs	mtcsys;
};

extern const struct tsens_data data_tsens2xxx, data_tsens23xx, data_tsens24xx;
extern struct list_head tsens_device_list;

#endif /* __QCOM_TSENS_H__ */
Loading