aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnsuel Smith <ansuelsmth@gmail.com>2019-12-19 04:01:28 +0100
committerPetr Štetiar <ynezz@true.cz>2019-12-26 08:31:42 +0100
commit77f4d5c6bb8323ec67248176a5a2907475041a79 (patch)
treec164759fd55b66526c189dffc734ad129360c3b5
parenta666f817a27c01adb9d4e5d5a25367254b556a44 (diff)
downloadupstream-77f4d5c6bb8323ec67248176a5a2907475041a79.tar.gz
upstream-77f4d5c6bb8323ec67248176a5a2907475041a79.tar.bz2
upstream-77f4d5c6bb8323ec67248176a5a2907475041a79.zip
ipq806x: rework ipq806x specific tsense temp driver
Tsense driver for ipq806x have various problem. - Emit wrong error. On probing of this driver, nvmem driver can be not ready and this cause a EDEFER error. Actually this is not an error as the kernel will retry to probe the driver after the nvmem driver is loaded. - Use uninitialized value on trigger of critical temp - Doesn't free allocated memory Because of this, rework the driver and improve it by removing extra load of data. Change the logic of loading data. Use the backup calib data only when the calib data is not present. As the calibration is only needed to set the temp offset, we don't really need to read both calib data and set the offset based only on the backup one. Also change how the notifier function work. At times when we output the trigger message, we already have read the temp so remove the extra read and the wrong uninitialized data that probably caused a kernel panic for null pointer exception. (Think we never experience this bug because the router never reached that temp ever... So just lucky) Tested-by: Stefan Lippers-Hollmann <s.l-h@gmx.de> [nbg6817/ipq8065] Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
-rw-r--r--target/linux/ipq806x/patches-4.19/0063-4-ip806x-tsense-rework-driver.patch107
1 files changed, 107 insertions, 0 deletions
diff --git a/target/linux/ipq806x/patches-4.19/0063-4-ip806x-tsense-rework-driver.patch b/target/linux/ipq806x/patches-4.19/0063-4-ip806x-tsense-rework-driver.patch
new file mode 100644
index 0000000000..7092552559
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.19/0063-4-ip806x-tsense-rework-driver.patch
@@ -0,0 +1,107 @@
+--- a/drivers/thermal/qcom/tsens-ipq8064.c
++++ b/drivers/thermal/qcom/tsens-ipq8064.c
+@@ -13,10 +13,12 @@
+ */
+
+ #include <linux/platform_device.h>
++#include <linux/err.h>
+ #include <linux/delay.h>
+ #include <linux/bitops.h>
+ #include <linux/regmap.h>
+ #include <linux/thermal.h>
++#include <linux/slab.h>
+ #include <linux/nvmem-consumer.h>
+ #include <linux/io.h>
+ #include <linux/interrupt.h>
+@@ -210,9 +212,8 @@
+ struct tsens_device *tmdev = container_of(work, struct tsens_device,
+ tsens_work);
+ unsigned int threshold, threshold_low, code, reg, sensor, mask;
+- unsigned int sensor_addr;
+ bool upper_th_x, lower_th_x;
+- int adc_code, ret;
++ int ret;
+
+ ret = regmap_read(tmdev->map, STATUS_CNTL_8064, &reg);
+ if (ret)
+@@ -261,9 +262,8 @@
+ if (upper_th_x || lower_th_x) {
+ /* Notify user space */
+ schedule_work(&tmdev->sensor[0].notify_work);
+- regmap_read(tmdev->map, sensor_addr, &adc_code);
+ pr_debug("Trigger (%d degrees) for sensor %d\n",
+- code_to_degC(adc_code, &tmdev->sensor[0]), 0);
++ code_to_degC(code, &tmdev->sensor[0]), 0);
+ }
+ }
+ regmap_write(tmdev->map, STATUS_CNTL_8064, reg & mask);
+@@ -372,40 +372,55 @@
+ static int calibrate_ipq8064(struct tsens_device *tmdev)
+ {
+ int i;
+- char *data, *data_backup;
+-
++ int ret = 0;
++ u8 *data, *data_backup;
++ struct device *dev = tmdev->dev;
+ ssize_t num_read = tmdev->num_sensors;
+ struct tsens_sensor *s = tmdev->sensor;
+
+- data = qfprom_read(tmdev->dev, "calib");
++ data = qfprom_read(dev, "calib");
+ if (IS_ERR(data)) {
+- pr_err("Calibration not found.\n");
+- return PTR_ERR(data);
++ ret = PTR_ERR(data);
++ if (ret != -EPROBE_DEFER)
++ dev_err(dev, "Calibration not found.");
++ goto exit;
+ }
+
+- data_backup = qfprom_read(tmdev->dev, "calib_backup");
++ data_backup = qfprom_read(dev, "calib_backup");
+ if (IS_ERR(data_backup)) {
+- pr_err("Backup calibration not found.\n");
+- return PTR_ERR(data_backup);
++ ret = PTR_ERR(data_backup);
++ if (ret != -EPROBE_DEFER)
++ dev_err(dev, "Backup Calibration not found.");
++ goto free_data;
+ }
+
+ for (i = 0; i < num_read; i++) {
+ s[i].calib_data = readb_relaxed(data + i);
+- s[i].calib_data_backup = readb_relaxed(data_backup + i);
++
++ if (!s[i].calib_data) {
++ s[i].calib_data_backup = readb_relaxed(data_backup + i);
++
++ if (!s[i].calib_data_backup) {
++ dev_err(dev, "QFPROM TSENS calibration data not present");
++ ret = -ENODEV;
++ goto free_backup;
++ }
+
+- if (s[i].calib_data_backup)
+ s[i].calib_data = s[i].calib_data_backup;
+- if (!s[i].calib_data) {
+- pr_err("QFPROM TSENS calibration data not present\n");
+- return -ENODEV;
+ }
++
+ s[i].slope = tsens_8064_slope[i];
+ s[i].offset = CAL_MDEGC - (s[i].calib_data * s[i].slope);
+ }
+
+ hw_init(tmdev);
+
+- return 0;
++free_backup:
++ kfree(data_backup);
++free_data:
++ kfree(data);
++exit:
++ return ret;
+ }
+
+ static int get_temp_ipq8064(struct tsens_device *tmdev, int id, int *temp)