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

Commit 7b3e424f authored by Jishnu Prakash's avatar Jishnu Prakash Committed by Siva Kumar Akkireddi
Browse files

thermal: tsens: Add support for TSENS min temp and 0C interrupt



Add support to read min_temp sensor, to get least temperature of
all TSENS sensors. Add support to use 0C interrupt, which is
triggered when any sensor temperature falls below SET threshold
and also when all sensor temperatures have passed above RESET threshold,
to clear mitigation.

Change-Id: I59d81dd8730c3021b90d369d036613a9015f76f3
Signed-off-by: default avatarJishnu Prakash <jprakash@codeaurora.org>
Signed-off-by: default avatarSiva Kumar Akkireddi <sivaa@codeaurora.org>
parent 2b85740d
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -25,6 +25,13 @@ static int tsens_get_temp(void *data, int *temp)
	return tmdev->ops->get_temp(s, temp);
}

static int tsens_get_min_temp(void *data, int *temp)
{
	struct tsens_sensor *s = data;

	return tsens_2xxx_get_min_temp(s, temp);
}

static int tsens_set_trip_temp(void *data, int low_temp, int high_temp)
{
	struct tsens_sensor *s = data;
@@ -82,6 +89,9 @@ static const struct of_device_id tsens_table[] = {
	{	.compatible = "qcom,tsens24xx",
		.data = &data_tsens24xx,
	},
	{	.compatible = "qcom,tsens26xx",
		.data = &data_tsens26xx,
	},
	{	.compatible = "qcom,msm8937-tsens",
		.data = &data_tsens14xx,
	},
@@ -97,6 +107,10 @@ static struct thermal_zone_of_device_ops tsens_tm_thermal_zone_ops = {
	.set_trips = tsens_set_trip_temp,
};

static struct thermal_zone_of_device_ops tsens_tm_min_thermal_zone_ops = {
	.get_temp = tsens_get_min_temp,
};

static int get_device_tree_data(struct platform_device *pdev,
				struct tsens_device *tmdev)
{
@@ -105,6 +119,7 @@ static int get_device_tree_data(struct platform_device *pdev,
	const struct tsens_data *data;
	int rc = 0;
	struct resource *res_tsens_mem;
	u32 min_temp_id;

	if (!of_match_node(tsens_table, of_node)) {
		pr_err("Need to read SoC specific fuse map\n");
@@ -179,6 +194,11 @@ static int get_device_tree_data(struct platform_device *pdev,
		}
	}

	if (!of_property_read_u32(of_node, "0C-sensor-num", &min_temp_id))
		tmdev->min_temp_sensor_id = (int)min_temp_id;
	else
		tmdev->min_temp_sensor_id = MIN_TEMP_DEF_OFFSET;

	return rc;
}

@@ -209,6 +229,17 @@ static int tsens_thermal_zone_register(struct tsens_device *tmdev)
		return -ENODEV;
	}

	if (tmdev->min_temp_sensor_id != MIN_TEMP_DEF_OFFSET) {
		tmdev->min_temp.tmdev = tmdev;
		tmdev->min_temp.hw_id = tmdev->min_temp_sensor_id;
		tmdev->min_temp.tzd =
			devm_thermal_zone_of_sensor_register(
			&tmdev->pdev->dev, tmdev->min_temp_sensor_id,
			&tmdev->min_temp, &tsens_tm_min_thermal_zone_ops);
		if (IS_ERR(tmdev->min_temp.tzd))
			pr_err("Error registering min temp sensor\n");
	}

	/* Register virtual thermal sensors. */
	qti_virtual_sensor_register(&tmdev->pdev->dev);

+8 −1
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@
#define SLOPE_DEFAULT		3200

#define IPC_LOGPAGES 10
#define MIN_TEMP_DEF_OFFSET		0xFF

enum tsens_dbg_type {
	TSENS_DBG_POLL,
@@ -208,14 +209,20 @@ struct tsens_device {
	const struct tsens_data		*ctrl_data;
	struct tsens_mtc_sysfs  mtcsys;
	int				trdy_fail_ctr;
	struct tsens_sensor		min_temp;
	u8				min_temp_sensor_id;
	struct tsens_sensor		sensor[0];
};

extern const struct tsens_data data_tsens2xxx, data_tsens23xx, data_tsens24xx;
extern const struct tsens_data data_tsens2xxx, data_tsens23xx, data_tsens24xx,
		data_tsens26xx;
extern const struct tsens_data data_tsens14xx, data_tsens14xx_405;
extern struct list_head tsens_device_list;

extern int calibrate_8937(struct tsens_device *tmdev);
extern int calibrate_405(struct tsens_device *tmdev);

extern int tsens_2xxx_get_min_temp(
		struct tsens_sensor *sensor, int *temp);

#endif /* __QCOM_TSENS_H__ */
+126 −5
Original line number Diff line number Diff line
@@ -42,12 +42,15 @@
#define TSENS_TM_UPPER_LOWER_INT_MASK(n)	((n) + 0x10)
#define TSENS_TM_UPPER_INT_SET(n)		(1 << (n + 16))
#define TSENS_TM_SN_CRITICAL_THRESHOLD_MASK	0xfff
#define TSENS_TM_MIN_TEMP_VALID_BIT		BIT(16)
#define TSENS_TM_SN_STATUS_VALID_BIT		BIT(21)
#define TSENS_TM_SN_STATUS_CRITICAL_STATUS	BIT(19)
#define TSENS_TM_SN_STATUS_UPPER_STATUS		BIT(18)
#define TSENS_TM_SN_STATUS_LOWER_STATUS		BIT(17)
#define TSENS_TM_SN_LAST_TEMP_MASK		0xfff
#define TSENS_TM_CODE_BIT_MASK			0xfff
#define TSENS_TM_0C_THR_MASK			0xfff
#define TSENS_TM_0C_THR_OFFSET			12
#define TSENS_TM_CODE_SIGN_BIT			0x800
#define TSENS_TM_SCALE_DECI_MILLIDEG		100
#define TSENS_DEBUG_WDOG_TRIGGER_COUNT		5
@@ -58,6 +61,10 @@
#define TSENS_TM_TRDY(n)			((n) + 0xe4)
#define TSENS_TM_TRDY_FIRST_ROUND_COMPLETE	BIT(3)
#define TSENS_TM_TRDY_FIRST_ROUND_COMPLETE_SHIFT	3
#define TSENS_TM_0C_INT_STATUS(n)	((n) + 0xe0)
#define TSENS_TM_MIN_TEMP(n)	((n) + 0xec)
#define TSENS_TM_0C_THRESHOLDS(n)		((n) + 0x1c)
#define TSENS_MAX_READ_FAIL			50

static void msm_tsens_convert_temp(int last_temp, int *temp)
{
@@ -92,7 +99,7 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp)
			code, tmdev->trdy_fail_ctr);
		tmdev->trdy_fail_ctr++;

		if (tmdev->trdy_fail_ctr >= 50) {
		if (tmdev->trdy_fail_ctr >= TSENS_MAX_READ_FAIL) {
			if (tmdev->ops->dbg)
				tmdev->ops->dbg(tmdev, 0,
					TSENS_DBG_LOG_BUS_ID_DATA, NULL);
@@ -147,6 +154,75 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp)
	return 0;
}

int tsens_2xxx_get_min_temp(struct tsens_sensor *sensor, int *temp)
{
	struct tsens_device *tmdev = NULL;
	unsigned int code;
	void __iomem *sensor_addr, *trdy;
	int last_temp = 0, last_temp2 = 0, last_temp3 = 0, valid_bit;

	if (!sensor)
		return -EINVAL;

	tmdev = sensor->tmdev;
	trdy = TSENS_TM_TRDY(tmdev->tsens_tm_addr);

	valid_bit = TSENS_TM_MIN_TEMP_VALID_BIT;
	sensor_addr = TSENS_TM_MIN_TEMP(tmdev->tsens_tm_addr);

	code = readl_relaxed_no_log(trdy);
	if (!((code & TSENS_TM_TRDY_FIRST_ROUND_COMPLETE) >>
			TSENS_TM_TRDY_FIRST_ROUND_COMPLETE_SHIFT)) {
		pr_err("tsens device first round not complete0x%x, ctr is %d\n",
			code, tmdev->trdy_fail_ctr);
		tmdev->trdy_fail_ctr++;
		if (tmdev->trdy_fail_ctr >= TSENS_MAX_READ_FAIL) {
			if (tmdev->ops->dbg)
				tmdev->ops->dbg(tmdev, 0,
					TSENS_DBG_LOG_BUS_ID_DATA, NULL);
			BUG();
		}
		return -ENODATA;
	}

	tmdev->trdy_fail_ctr = 0;

	code = readl_relaxed_no_log(sensor_addr);
	last_temp = code & TSENS_TM_SN_LAST_TEMP_MASK;
	if (code & valid_bit) {
		msm_tsens_convert_temp(last_temp, temp);
		goto dbg;
	}

	code = readl_relaxed_no_log(sensor_addr);
	last_temp2 = code & TSENS_TM_SN_LAST_TEMP_MASK;
	if (code & valid_bit) {
		last_temp = last_temp2;
		msm_tsens_convert_temp(last_temp, temp);
		goto dbg;
	}

	code = readl_relaxed_no_log(sensor_addr);
	last_temp3 = code & TSENS_TM_SN_LAST_TEMP_MASK;
	if (code & valid_bit) {
		last_temp = last_temp3;
		msm_tsens_convert_temp(last_temp, temp);
		goto dbg;
	}

	if (last_temp == last_temp2)
		last_temp = last_temp2;
	else if (last_temp2 == last_temp3)
		last_temp = last_temp3;

	msm_tsens_convert_temp(last_temp, temp);

dbg:
	TSENS_DBG(tmdev, "Min temp: %d\n", *temp);

	return 0;
}

static int tsens_tm_activate_trip_type(struct tsens_sensor *tm_sensor,
			int trip, enum thermal_device_mode mode)
{
@@ -518,6 +594,31 @@ static irqreturn_t tsens_tm_irq_thread(int irq, void *data)
	return IRQ_HANDLED;
}

static irqreturn_t tsens_tm_0C_irq_thread(int irq, void *data)
{
	struct tsens_device *tm = data;
	int status, thrs, set_thr, reset_thr;
	void __iomem *srot_addr, *addr;

	addr = TSENS_TM_0C_INT_STATUS(tm->tsens_tm_addr);
	status = readl_relaxed(addr);

	srot_addr = TSENS_CTRL_ADDR(tm->tsens_srot_addr);
	thrs = readl_relaxed(TSENS_TM_0C_THRESHOLDS(srot_addr));

	msm_tsens_convert_temp(thrs & TSENS_TM_0C_THR_MASK, &reset_thr);
	msm_tsens_convert_temp(
		((thrs >> TSENS_TM_0C_THR_OFFSET) &
				TSENS_TM_0C_THR_MASK), &set_thr);

	if (status)
		of_thermal_handle_trip_temp(tm->min_temp.tzd, set_thr);
	else
		of_thermal_handle_trip_temp(tm->min_temp.tzd, reset_thr);

	return IRQ_HANDLED;
}

static int tsens2xxx_hw_sensor_en(struct tsens_device *tmdev,
					u32 sensor_id)
{
@@ -602,19 +703,26 @@ static int tsens2xxx_hw_init(struct tsens_device *tmdev)
static const struct tsens_irqs tsens2xxx_irqs[] = {
	{ "tsens-upper-lower", tsens_tm_irq_thread},
	{ "tsens-critical", tsens_tm_critical_irq_thread},
	{ "tsens-0C", tsens_tm_0C_irq_thread},
};

static int tsens2xxx_register_interrupts(struct tsens_device *tmdev)
{
	struct platform_device *pdev;
	int i, rc;
	int i, rc, irq_no;
	unsigned long irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;

	if (!tmdev)
		return -EINVAL;

	if (tmdev->min_temp_sensor_id != MIN_TEMP_DEF_OFFSET)
		irq_no = ARRAY_SIZE(tsens2xxx_irqs);
	else
		irq_no = ARRAY_SIZE(tsens2xxx_irqs) - 1;

	pdev = tmdev->pdev;

	for (i = 0; i < ARRAY_SIZE(tsens2xxx_irqs); i++) {
	for (i = 0; i < irq_no; i++) {
		int irq;

		irq = platform_get_irq_byname(pdev, tsens2xxx_irqs[i].name);
@@ -624,10 +732,12 @@ static int tsens2xxx_register_interrupts(struct tsens_device *tmdev)
			return irq;
		}

		if (i == 2)
			irqflags = IRQF_TRIGGER_RISING | IRQF_ONESHOT;

		rc = devm_request_threaded_irq(&pdev->dev, irq, NULL,
				tsens2xxx_irqs[i].handler,
				IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
				tsens2xxx_irqs[i].name, tmdev);
				irqflags, tsens2xxx_irqs[i].name, tmdev);
		if (rc) {
			dev_err(&pdev->dev, "failed to get irq %s\n",
					tsens2xxx_irqs[i].name);
@@ -677,3 +787,14 @@ const struct tsens_data data_tsens24xx = {
	.ops				= &ops_tsens2xxx,
	.mtc				= false,
};

const struct tsens_data data_tsens26xx = {
	.cycle_monitor			= true,
	.cycle_compltn_monitor_mask	= 1,
	.wd_bark			= true,
	.wd_bark_mask			= 0,
	.ops				= &ops_tsens2xxx,
	.mtc				= false,
	.ver_major			= 2,
	.ver_minor			= 6,
};