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

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

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

parents 5564dc86 7b3e424f
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,
};