summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSiddartha Mohanadoss <smohanad@codeaurora.org>2016-02-17 12:41:47 -0800
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:10:25 -0700
commit2021d15137a3095f3f2c0e55fe36bbdc96cd64ba (patch)
treea9ed70d709bebb594ac02ced716f3f9d17eb0ab1
parent31d2a03e6e7c43169cbc7df9c0884da9363a58a3 (diff)
thermal: tsens: Enable TSENS
This snapshot is taken as of msm-3.18 commit dbdb6776f (Merge "msm: camera: Add dummy sub module in sensor pipeline") Commit 0b46b8a7 (clocksource: arch_timer: Fix code to use physical timers when requested) introduces the use of physical counters and requires clients to use api arch_counter_get_cntvct(). Accordingly update tsens_poll() to the new API to prevent a BUG_ON() during bootup. Fixup TSENS to use supported int type for temperature value. Signed-off-by: Siddartha Mohanadoss <smohanad@codeaurora.org>
-rw-r--r--Documentation/devicetree/bindings/thermal/tsens.txt22
-rw-r--r--drivers/thermal/Makefile2
-rw-r--r--drivers/thermal/msm-tsens.c (renamed from drivers/thermal/msm8974-tsens.c)2421
-rw-r--r--include/linux/msm_tsens.h126
4 files changed, 2282 insertions, 289 deletions
diff --git a/Documentation/devicetree/bindings/thermal/tsens.txt b/Documentation/devicetree/bindings/thermal/tsens.txt
index dcbe9238328f..725bee029004 100644
--- a/Documentation/devicetree/bindings/thermal/tsens.txt
+++ b/Documentation/devicetree/bindings/thermal/tsens.txt
@@ -20,6 +20,15 @@ Required properties:
should be "qcom,msm8994-tsens" for 8994 TSENS driver.
should be "qcom,msm8996-tsens" for 8996 TSENS driver.
should be "qcom,msm8992-tsens" for 8992 TSENS driver.
+ should be "qcom,msm8916-tsens" for 8916 TSENS driver.
+ should be "qcom,msm8939-tsens" for 8939 TSENS driver.
+ should be "qcom,msm8909-tsens" for 8909 TSENS driver.
+ should be "qcom,msm8952-tsens" for 8952 TSENS driver.
+ should be "qcom,msmzirc-tsens" for zirc TSENS driver.
+ should be "qcom,mdm9607-tsens" for 9607 TSENS driver.
+ should be "qcom,msmtitanium-tsens" for titanium TSENS driver.
+ should be "qcom,msm8937-tsens" for 8937 TSENS driver.
+ should be "qcom,msmgold-tsens" for gold TSENS driver.
The compatible property is used to identify the respective fusemap to use
for the corresponding SoC.
- reg : offset and length of the TSENS registers.
@@ -54,6 +63,19 @@ Optional properties:
- qcom,sensor-id : If the flag is present map the TSENS sensors based on the
remote sensors that are enabled in HW. Ensure the mapping is not
more than the number of supported sensors.
+- qcom,client-id : If the flag is present use it to identify the SW ID mapping
+ used to associate it with the controller and the physical sensor
+ mapping within the controller. The physical sensor mapping within
+ each controller is done using the qcom,sensor-id property. If the
+ property is not present the SW ID mapping with default from 0 to
+ total number of supported sensors with each controller instance.
+- qcom,valid-status-check: If property is present, check the VALID bit is set
+ before reporting the temperature data.
+- qcom,temp1-offset: If property is present, Use these offset values
+ to be added for 30 deg calib points.
+- qcom,temp2-offset: If property is present, Use these offset values
+ to be added for 120 deg calib points.
+
Example:
tsens@fc4a8000 {
diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile
index cbfff2226bcd..22abb6a161a0 100644
--- a/drivers/thermal/Makefile
+++ b/drivers/thermal/Makefile
@@ -50,7 +50,7 @@ obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o
obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o
obj-$(CONFIG_THERMAL_QPNP) += qpnp-temp-alarm.o
obj-$(CONFIG_THERMAL_QPNP_ADC_TM) += qpnp-adc-tm.o
-obj-$(CONFIG_THERMAL_TSENS8974) += msm8974-tsens.o
+obj-$(CONFIG_THERMAL_TSENS8974) += msm-tsens.o
obj-$(CONFIG_THERMAL_MONITOR) += msm_thermal.o msm_thermal-dev.o
obj-$(CONFIG_LIMITS_MONITOR) += lmh_interface.o
obj-$(CONFIG_LIMITS_LITE_HW) += lmh_lite.o
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm-tsens.c
index d5cfedca6336..9d7f697960bf 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm-tsens.c
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <linux/thermal.h>
#include <linux/interrupt.h>
+#include <linux/workqueue.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/io.h>
@@ -24,6 +25,9 @@
#include <linux/msm_tsens.h>
#include <linux/err.h>
#include <linux/of.h>
+#include <linux/debugfs.h>
+#include <linux/vmalloc.h>
+#include <asm/arch_timer.h>
#define CREATE_TRACE_POINTS
#include <trace/trace_thermal.h>
@@ -55,6 +59,29 @@
#define TSENS2_SN_STATUS_VALID_MASK 0x4000
#define TSENS2_TRDY_ADDR(n) ((n) + 0x84)
+#define TSENS4_TRDY_ADDR(n) ((n) + 0x1084)
+
+#define TSENS_MTC_ZONE0_SW_MASK_ADDR(n) ((n) + 0x10c0)
+#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_MTC_ZONE0_LOG(n) ((n) + 0x10d0)
+#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
+
/* TSENS_TM registers for 8996 */
#define TSENS_TM_INT_EN(n) ((n) + 0x1004)
#define TSENS_TM_CRITICAL_INT_EN BIT(2)
@@ -94,6 +121,19 @@
#define TSENS_TM_CODE_BIT_MASK 0xfff
#define TSENS_TM_CODE_SIGN_BIT 0x800
+#define TSENS_CONTROLLER_ID(n) ((n) + 0x1000)
+#define TSENS_DEBUG_CONTROL(n) ((n) + 0x1130)
+#define TSENS_DEBUG_DATA(n) ((n) + 0x1134)
+#define TSENS_TM_MTC_ZONE0_SW_MASK_ADDR(n) ((n) + 0x1140)
+#define TSENS_TM_MTC_ZONE0_LOG(n) ((n) + 0x1150)
+#define TSENS_TM_MTC_ZONE0_HISTORY(n) ((n) + 0x1160)
+#define TSENS_RESET_HISTORY_MASK 0x4
+#define TSENS_RESET_HISTORY_SHIFT 2
+#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
/* End TSENS_TM registers for 8996 */
#define TSENS_CTRL_ADDR(n) (n)
@@ -348,6 +388,7 @@
#define TSENS_TYPE0 0
#define TSENS_TYPE2 2
#define TSENS_TYPE3 3
+#define TSENS_TYPE4 4
#define TSENS_8916_BASE0_MASK 0x0000007f
#define TSENS_8916_BASE1_MASK 0xfe000000
@@ -554,6 +595,137 @@
#define TSENS4_OFFSET_ZIRC_MASK 0xf0
#define TSENS4_OFFSET_ZIRC_SHIFT 4
+#define TSENS_CONTR_14_BASE0_MASK 0x000000ff
+#define TSENS_CONTR_14_BASE1_MASK 0xff000000
+
+#define TSENS0_CONTR_14_POINT1_MASK 0x000001f8
+#define TSENS1_CONTR_14_POINT1_MASK 0x001f8000
+#define TSENS2_CONTR_14_POINT1_MASK_0_4 0xf8000000
+#define TSENS2_CONTR_14_POINT1_MASK_5 0x00000001
+#define TSENS3_CONTR_14_POINT1_MASK 0x00001f80
+#define TSENS4_CONTR_14_POINT1_MASK 0x01f80000
+#define TSENS5_CONTR_14_POINT1_MASK 0x00003f00
+#define TSENS6_CONTR_14_POINT1_MASK 0x03f00000
+#define TSENS7_CONTR_14_POINT1_MASK 0x0000003f
+#define TSENS8_CONTR_14_POINT1_MASK 0x0003f000
+#define TSENS9_CONTR_14_POINT1_MASK 0x0000003f
+#define TSENS10_CONTR_14_POINT1_MASK 0x0003f000
+
+#define TSENS0_CONTR_14_POINT2_MASK 0x00007e00
+#define TSENS1_CONTR_14_POINT2_MASK 0x07e00000
+#define TSENS2_CONTR_14_POINT2_MASK 0x0000007e
+#define TSENS3_CONTR_14_POINT2_MASK 0x0007e000
+#define TSENS4_CONTR_14_POINT2_MASK 0x7e000000
+#define TSENS5_CONTR_14_POINT2_MASK 0x000fc000
+#define TSENS6_CONTR_14_POINT2_MASK 0xfc000000
+#define TSENS7_CONTR_14_POINT2_MASK 0x00000fc0
+#define TSENS8_CONTR_14_POINT2_MASK 0x00fc0000
+#define TSENS9_CONTR_14_POINT2_MASK 0x00000fc0
+#define TSENS10_CONTR_14_POINT2_MASK 0x00fc0000
+
+#define TSENS_CONTR_14_TSENS_CAL_SEL 0x00000007
+#define TSENS_CONTR_14_BASE1_SHIFT 24
+
+#define TSENS0_CONTR_14_POINT1_SHIFT 3
+#define TSENS1_CONTR_14_POINT1_SHIFT 15
+#define TSENS2_CONTR_14_POINT1_SHIFT_0_4 27
+#define TSENS2_CONTR_14_POINT1_SHIFT_5 5
+#define TSENS3_CONTR_14_POINT1_SHIFT 7
+#define TSENS4_CONTR_14_POINT1_SHIFT 19
+#define TSENS5_CONTR_14_POINT1_SHIFT 8
+#define TSENS6_CONTR_14_POINT1_SHIFT 20
+#define TSENS8_CONTR_14_POINT1_SHIFT 12
+#define TSENS10_CONTR_14_POINT1_SHIFT 12
+
+#define TSENS0_CONTR_14_POINT2_SHIFT 9
+#define TSENS1_CONTR_14_POINT2_SHIFT 21
+#define TSENS2_CONTR_14_POINT2_SHIFT 1
+#define TSENS3_CONTR_14_POINT2_SHIFT 13
+#define TSENS4_CONTR_14_POINT2_SHIFT 25
+#define TSENS5_CONTR_14_POINT2_SHIFT 14
+#define TSENS6_CONTR_14_POINT2_SHIFT 26
+#define TSENS7_CONTR_14_POINT2_SHIFT 6
+#define TSENS8_CONTR_14_POINT2_SHIFT 18
+#define TSENS9_CONTR_14_POINT2_SHIFT 6
+#define TSENS10_CONTR_14_POINT2_SHIFT 18
+
+#define TSENS_TWO_POINT_CALIB_N_WA 0x6
+#define TSENS_TWO_POINT_CALIB_N_OFFSET_WA 0x7
+
+#define TSENS_MSM8952_D30_WA_S0 2
+#define TSENS_MSM8952_D30_WA_S1 4
+#define TSENS_MSM8952_D30_WA_S2 4
+#define TSENS_MSM8952_D30_WA_S3 1
+#define TSENS_MSM8952_D30_WA_S4 2
+#define TSENS_MSM8952_D30_WA_S5 1
+#define TSENS_MSM8952_D30_WA_S7 3
+#define TSENS_MSM8952_D30_WA_S8 2
+#define TSENS_MSM8952_D30_WA_S10 3
+
+#define TSENS_MSM8952_D120_WA_S0 1
+#define TSENS_MSM8952_D120_WA_S1 4
+#define TSENS_MSM8952_D120_WA_S2 5
+#define TSENS_MSM8952_D120_WA_S3 1
+#define TSENS_MSM8952_D120_WA_S4 3
+#define TSENS_MSM8952_D120_WA_S5 1
+#define TSENS_MSM8952_D120_WA_S6 1
+#define TSENS_MSM8952_D120_WA_S7 4
+#define TSENS_MSM8952_D120_WA_S8 4
+#define TSENS_MSM8952_D120_WA_S10 2
+
+#define TSENS_NO_CALIB_POINT1_DATA 500
+#define TSENS_NO_CALIB_POINT2_DATA 780
+
+#define TSENS_MDM9607_TSENS_CAL_SEL 0x00700000
+#define TSENS_MDM9607_CAL_SEL_SHIFT 20
+#define TSENS_MDM9607_BASE1_SHIFT 12
+
+#define TSENS_MDM9607_BASE0_MASK 0x000000ff
+#define TSENS_MDM9607_BASE1_MASK 0x000ff000
+
+#define TSENS0_MDM9607_POINT1_MASK 0x00003f00
+#define TSENS1_MDM9607_POINT1_MASK 0x03f00000
+#define TSENS2_MDM9607_POINT1_MASK 0x0000003f
+#define TSENS3_MDM9607_POINT1_MASK 0x0003f000
+#define TSENS4_MDM9607_POINT1_MASK 0x0000003f
+
+#define TSENS0_MDM9607_POINT2_MASK 0x000fc000
+#define TSENS1_MDM9607_POINT2_MASK 0xfc000000
+#define TSENS2_MDM9607_POINT2_MASK 0x00000fc0
+#define TSENS3_MDM9607_POINT2_MASK 0x00fc0000
+#define TSENS4_MDM9607_POINT2_MASK 0x0000fc00
+
+#define TSENS0_MDM9607_POINT1_SHIFT 8
+#define TSENS1_MDM9607_POINT1_SHIFT 20
+#define TSENS3_MDM9607_POINT1_SHIFT 12
+
+#define TSENS0_MDM9607_POINT2_SHIFT 14
+#define TSENS1_MDM9607_POINT2_SHIFT 26
+#define TSENS2_MDM9607_POINT2_SHIFT 6
+#define TSENS3_MDM9607_POINT2_SHIFT 18
+#define TSENS4_MDM9607_POINT2_SHIFT 6
+
+/* debug defines */
+#define TSENS_DBG_BUS_ID_0 0
+#define TSENS_DBG_BUS_ID_1 1
+#define TSENS_DBG_BUS_ID_15 15
+#define TSENS_DEBUG_LOOP_COUNT_ID_0 30
+#define TSENS_DEBUG_LOOP_COUNT 5
+#define TSENS_DEBUG_STATUS_REG_START 10
+#define TSENS_DEBUG_OFFSET_RANGE 16
+#define TSENS_DEBUG_OFFSET_WORD1 0x4
+#define TSENS_DEBUG_OFFSET_WORD2 0x8
+#define TSENS_DEBUG_OFFSET_WORD3 0xc
+#define TSENS_DEBUG_OFFSET_ROW 0x10
+#define TSENS_DEBUG_DECIDEGC -400
+#define TSENS_DEBUG_MIN_CYCLE 63000
+#define TSENS_DEBUG_MAX_CYCLE 64000
+#define TSENS_DEBUG_ID_MASK_1_4 0xffffffe1
+
+static uint32_t tsens_sec_to_msec_value = 3000;
+static uint32_t tsens_completion_timeout_hz = 2 * HZ;
+static uint32_t tsens_poll_check = 1;
+
enum tsens_calib_fuse_map_type {
TSENS_CALIB_FUSE_MAP_8974 = 0,
TSENS_CALIB_FUSE_MAP_8X26,
@@ -567,6 +739,10 @@ enum tsens_calib_fuse_map_type {
TSENS_CALIB_FUSE_MAP_MSMZIRC,
TSENS_CALIB_FUSE_MAP_NONE,
TSENS_CALIB_FUSE_MAP_8992,
+ TSENS_CALIB_FUSE_MAP_MSM8952,
+ TSENS_CALIB_FUSE_MAP_MDM9607,
+ TSENS_CALIB_FUSE_MAP_MSM8937,
+ TSENS_CALIB_FUSE_MAP_MSMGOLD,
TSENS_CALIB_FUSE_MAP_NUM,
};
@@ -587,18 +763,38 @@ enum tsens_tm_trip_type {
#define TSENS_WRITABLE_TRIPS_MASK ((1 << TSENS_TRIP_NUM) - 1)
#define TSENS_TM_WRITABLE_TRIPS_MASK ((1 << TSENS_TM_TRIP_NUM) - 1)
+struct tsens_thrshld_state {
+ enum thermal_device_mode high_th_state;
+ enum thermal_device_mode low_th_state;
+ enum thermal_device_mode crit_th_state;
+ unsigned int high_adc_code;
+ unsigned int low_adc_code;
+ int high_temp;
+ int low_temp;
+ int crit_temp;
+};
+
struct tsens_tm_device_sensor {
struct thermal_zone_device *tz_dev;
+ struct tsens_tm_device *tm;
enum thermal_device_mode mode;
/* Physical HW sensor number */
unsigned int sensor_hw_num;
/* Software index. This is keep track of the HW/SW
* sensor_ID mapping */
unsigned int sensor_sw_id;
+ unsigned int sensor_client_id;
int offset;
int calib_data_point1;
int calib_data_point2;
uint32_t slope_mul_tsens_factor;
+ struct tsens_thrshld_state debug_thr_state_copy;
+ /* dbg_adc_code logs either the raw ADC code or temperature values in
+ * decidegC based on the controller settings.
+ */
+ int dbg_adc_code;
+ u32 wa_temp1_calib_offset_factor;
+ u32 wa_temp2_calib_offset_factor;
};
struct tsens_dbg_counter {
@@ -611,11 +807,21 @@ struct tsens_sensor_dbg_info {
unsigned long temp[10];
uint32_t idx;
unsigned long long time_stmp[10];
+ int adccode[10];
+};
+
+struct tsens_mtc_sysfs {
+ uint32_t zone_log;
+ int zone_mtc;
+ int th1;
+ int th2;
+ uint32_t zone_hist;
};
struct tsens_tm_device {
struct platform_device *pdev;
struct workqueue_struct *tsens_critical_wq;
+ struct list_head list;
bool is_ready;
bool prev_reading_avail;
bool calibration_less_mode;
@@ -635,13 +841,184 @@ struct tsens_tm_device {
bool tsens_valid_status_check;
struct tsens_dbg_counter tsens_thread_iq_dbg;
struct tsens_sensor_dbg_info sensor_dbg_info[16];
+ int tsens_upper_irq_cnt;
+ int tsens_lower_irq_cnt;
+ int tsens_critical_irq_cnt;
+ struct delayed_work tsens_critical_poll_test;
+ struct completion tsens_rslt_completion;
+ struct tsens_mtc_sysfs mtcsys;
+ spinlock_t tsens_crit_lock;
+ spinlock_t tsens_upp_low_lock;
+ bool crit_set;
+ unsigned long long crit_timestamp_last_run;
+ unsigned long long crit_timestamp_last_interrupt_handled;
+ unsigned long long crit_timestamp_last_poll_request;
+ u64 qtimer_val_detection_start;
+ u64 qtimer_val_last_detection_interrupt;
+ u64 qtimer_val_last_polling_check;
struct tsens_tm_device_sensor sensor[0];
};
-struct tsens_tm_device *tmdev;
+LIST_HEAD(tsens_device_list);
+
+static char dbg_buff[1024];
+static struct dentry *dent;
+static struct dentry *dfile_stats;
+
+static struct of_device_id tsens_match[] = {
+ { .compatible = "qcom,msm-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_8974,
+ },
+ { .compatible = "qcom,msm8x26-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_8X26,
+ },
+ { .compatible = "qcom,msm8x10-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_8X10,
+ },
+ { .compatible = "qcom,fsm9900-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_9900,
+ },
+ { .compatible = "qcom,mdm9630-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_9630,
+ },
+ { .compatible = "qcom,msm8916-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_8916,
+ },
+ { .compatible = "qcom,msm8939-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_8939,
+ },
+ { .compatible = "qcom,msm8994-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_8994,
+ },
+ { .compatible = "qcom,msm8909-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_MSM8909,
+ },
+ { .compatible = "qcom,msmzirc-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_MSMZIRC,
+ },
+ { .compatible = "qcom,msm8996-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_NONE,
+ },
+ { .compatible = "qcom,msm8992-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_8992,
+ },
+ { .compatible = "qcom,msm8952-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_MSM8952,
+ },
+ { .compatible = "qcom,mdm9607-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_MDM9607,
+ },
+ { .compatible = "qcom,msmtitanium-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_NONE,
+ },
+ { .compatible = "qcom,msm8937-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_MSM8937,
+ },
+ { .compatible = "qcom,msmgold-tsens",
+ .data = (void *)TSENS_CALIB_FUSE_MAP_MSMGOLD,
+ },
+ {}
+};
+
+static struct tsens_tm_device *tsens_controller_is_present(void)
+{
+ struct tsens_tm_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;
+}
+
+static int32_t get_tsens_sensor_for_client_id(struct tsens_tm_device *tmdev,
+ uint32_t sensor_client_id)
+{
+ bool id_found = false;
+ uint32_t i = 0;
+ struct device_node *of_node = NULL;
+ const struct of_device_id *id;
+
+ of_node = tmdev->pdev->dev.of_node;
+ if (of_node == NULL) {
+ pr_err("Invalid of_node??\n");
+ return -EINVAL;
+ }
+
+ if (!of_match_node(tsens_match, of_node)) {
+ pr_err("Need to read SoC specific fuse map\n");
+ return -ENODEV;
+ }
+
+ id = of_match_node(tsens_match, of_node);
+ if (id == NULL) {
+ pr_err("can not find tsens_match of_node\n");
+ return -ENODEV;
+ }
+
+ if (!strcmp(id->compatible, "qcom,msm8996-tsens")) {
+ while (i < tmdev->tsens_num_sensor && !id_found) {
+ if (tmdev->sensor[i].sensor_client_id ==
+ sensor_client_id) {
+ id_found = true;
+ return tmdev->sensor[i].sensor_hw_num;
+ }
+ i++;
+ }
+ } else
+ return sensor_client_id;
+
+ if (!id_found)
+ return -EINVAL;
+
+ return -EINVAL;
+}
+
+static struct tsens_tm_device *get_tsens_controller_for_client_id(
+ uint32_t sensor_client_id)
+{
+ struct tsens_tm_device *tmdev_chip = NULL;
+ bool id_found = false;
+ uint32_t i = 0;
+
+ list_for_each_entry(tmdev_chip, &tsens_device_list, list) {
+ i = 0;
+ while (i < tmdev_chip->tsens_num_sensor && !id_found) {
+ if (tmdev_chip->sensor[i].sensor_client_id ==
+ sensor_client_id) {
+ id_found = true;
+ return tmdev_chip;
+ }
+ i++;
+ }
+ }
+
+ if (!id_found)
+ return NULL;
+
+ return tmdev_chip;
+}
-int tsens_is_ready()
+static struct tsens_tm_device *get_all_tsens_controller_sensor_count(
+ uint32_t *sensor_count)
{
+ struct tsens_tm_device *tmdev_chip = NULL;
+
+ list_for_each_entry(tmdev_chip, &tsens_device_list, list)
+ *sensor_count += tmdev_chip->tsens_num_sensor;
+
+ return tmdev_chip;
+}
+
+int tsens_is_ready(void)
+{
+ struct tsens_tm_device *tmdev = NULL;
+
+ tmdev = tsens_controller_is_present();
if (!tmdev)
return -EPROBE_DEFER;
else
@@ -649,16 +1026,14 @@ int tsens_is_ready()
}
EXPORT_SYMBOL(tsens_is_ready);
-int tsens_get_sw_id_mapping(int sensor_hw_num, int *sensor_sw_idx)
+static int tsens_get_sw_id_mapping_for_controller(
+ int sensor_hw_num,
+ int *sensor_sw_idx,
+ struct tsens_tm_device *tmdev)
{
int i = 0;
bool id_found = false;
- if (tsens_is_ready() <= 0) {
- pr_debug("TSENS early init not done\n");
- return -EPROBE_DEFER;
- }
-
while (i < tmdev->tsens_num_sensor && !id_found) {
if (sensor_hw_num == tmdev->sensor[i].sensor_hw_num) {
*sensor_sw_idx = tmdev->sensor[i].sensor_sw_id;
@@ -672,24 +1047,62 @@ int tsens_get_sw_id_mapping(int sensor_hw_num, int *sensor_sw_idx)
return 0;
}
-EXPORT_SYMBOL(tsens_get_sw_id_mapping);
-int tsens_get_hw_id_mapping(int sensor_sw_id, int *sensor_hw_num)
+int tsens_get_hw_id_mapping(int sensor_sw_id, int *sensor_client_id)
{
int i = 0;
bool id_found = false;
+ struct tsens_tm_device *tmdev = NULL;
+ struct device_node *of_node = NULL;
+ const struct of_device_id *id;
- if (tsens_is_ready() <= 0) {
+ tmdev = get_tsens_controller_for_client_id(sensor_sw_id);
+ if (tmdev == NULL) {
pr_debug("TSENS early init not done\n");
return -EPROBE_DEFER;
}
- while (i < tmdev->tsens_num_sensor && !id_found) {
- if (sensor_sw_id == tmdev->sensor[i].sensor_sw_id) {
- *sensor_hw_num = tmdev->sensor[i].sensor_hw_num;
- id_found = true;
+ of_node = tmdev->pdev->dev.of_node;
+ if (of_node == NULL) {
+ pr_err("Invalid of_node??\n");
+ return -EINVAL;
+ }
+
+ if (!of_match_node(tsens_match, of_node)) {
+ pr_err("Need to read SoC specific fuse map\n");
+ return -ENODEV;
+ }
+
+ id = of_match_node(tsens_match, of_node);
+ if (id == NULL) {
+ pr_err("can not find tsens_match of_node\n");
+ return -ENODEV;
+ }
+
+ if (!strcmp(id->compatible, "qcom,msm8996-tsens")) {
+ /* Assign a client id which will be used to get the
+ * controller and hw_sensor details
+ */
+ while (i < tmdev->tsens_num_sensor && !id_found) {
+ if (sensor_sw_id == tmdev->sensor[i].sensor_client_id) {
+ *sensor_client_id =
+ tmdev->sensor[i].sensor_client_id;
+ id_found = true;
+ }
+ i++;
+ }
+ } else {
+ /* Assign the corresponding hw sensor number which is done
+ * prior to support for multiple controllres
+ */
+ while (i < tmdev->tsens_num_sensor && !id_found) {
+ if (sensor_sw_id == tmdev->sensor[i].sensor_client_id) {
+ *sensor_client_id =
+ tmdev->sensor[i].sensor_hw_num;
+ id_found = true;
+ }
+ i++;
}
- i++;
}
if (!id_found)
@@ -699,7 +1112,179 @@ int tsens_get_hw_id_mapping(int sensor_sw_id, int *sensor_hw_num)
}
EXPORT_SYMBOL(tsens_get_hw_id_mapping);
-static int tsens_tz_code_to_degc(int adc_code, int sensor_sw_id)
+static ssize_t
+zonemask_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct tsens_tm_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_tm_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_tm_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_tm_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_tm_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_tm_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 create_tsens_mtc_sysfs(struct platform_device *pdev)
+{
+ int result = 0, i;
+ struct device_attribute *attr_ptr = NULL;
+
+ attr_ptr = tsens_mtc_dev_attr;
+
+ for (i = 0; i < ARRAY_SIZE(tsens_mtc_dev_attr); i++) {
+ result = device_create_file(&pdev->dev, &attr_ptr[i]);
+ if (result < 0)
+ goto error;
+ }
+
+ pr_debug("create_tsens_mtc_sysfs success\n");
+
+ return result;
+
+error:
+ for (i--; i >= 0; i--)
+ device_remove_file(&pdev->dev, &attr_ptr[i]);
+
+ return result;
+}
+
+static int tsens_tz_code_to_degc(int adc_code, int sensor_sw_id,
+ struct tsens_tm_device *tmdev)
{
int degc, num, den, idx;
@@ -721,7 +1306,8 @@ static int tsens_tz_code_to_degc(int adc_code, int sensor_sw_id)
return degc;
}
-static int tsens_tz_degc_to_code(int degc, int idx)
+static int tsens_tz_degc_to_code(int degc, int idx,
+ struct tsens_tm_device *tmdev)
{
int code = ((degc * tmdev->sensor[idx].slope_mul_tsens_factor)
+ tmdev->sensor[idx].offset)/tmdev->tsens_factor;
@@ -735,7 +1321,7 @@ static int tsens_tz_degc_to_code(int degc, int idx)
return code;
}
-static void msm_tsens_get_temp(int sensor_hw_num, unsigned long *temp)
+static int msm_tsens_get_temp(int sensor_client_id, int *temp)
{
unsigned int code;
void __iomem *sensor_addr;
@@ -744,6 +1330,23 @@ static void msm_tsens_get_temp(int sensor_hw_num, unsigned long *temp)
int last_temp3 = 0, last_temp_mask, valid_status_mask, code_mask = 0;
bool last_temp_valid = false, last_temp2_valid = false;
bool last_temp3_valid = false;
+ struct tsens_tm_device *tmdev = NULL;
+ uint32_t sensor_hw_num = 0;
+
+ tmdev = get_tsens_controller_for_client_id(sensor_client_id);
+ if (tmdev == NULL) {
+ pr_err("TSENS early init not done\n");
+ return -EPROBE_DEFER;
+ }
+
+ pr_debug("sensor_client_id:%d\n", sensor_client_id);
+
+ sensor_hw_num = get_tsens_sensor_for_client_id(tmdev, sensor_client_id);
+ if (sensor_hw_num < 0) {
+ pr_err("cannot read the temperature\n");
+ return sensor_hw_num;
+ }
+ pr_debug("sensor_hw_num:%d\n", sensor_hw_num);
if (tmdev->tsens_type == TSENS_TYPE2) {
trdy_addr = TSENS2_TRDY_ADDR(tmdev->tsens_addr);
@@ -751,6 +1354,9 @@ static void msm_tsens_get_temp(int sensor_hw_num, unsigned long *temp)
} else if (tmdev->tsens_type == TSENS_TYPE3) {
trdy_addr = TSENS_TM_TRDY(tmdev->tsens_addr);
sensor_addr = TSENS_TM_SN_STATUS(tmdev->tsens_addr);
+ } else if (tmdev->tsens_type == TSENS_TYPE4) {
+ trdy_addr = TSENS4_TRDY_ADDR(tmdev->tsens_addr);
+ sensor_addr = TSENS2_SN_STATUS_ADDR(tmdev->tsens_addr);
} else {
trdy_addr = TSENS_TRDY_ADDR(tmdev->tsens_addr);
sensor_addr = TSENS_S0_STATUS_ADDR(tmdev->tsens_addr);
@@ -810,13 +1416,14 @@ static void msm_tsens_get_temp(int sensor_hw_num, unsigned long *temp)
if (tmdev->tsens_type != TSENS_TYPE3) {
/* Obtain SW index to map the corresponding thermal zone's
* offset and slope for code to degc conversion. */
- rc = tsens_get_sw_id_mapping(sensor_hw_num, &sensor_sw_id);
+ rc = tsens_get_sw_id_mapping_for_controller(sensor_hw_num,
+ &sensor_sw_id, tmdev);
if (rc < 0) {
pr_err("tsens mapping index not found\n");
- return;
+ return rc;
}
- *temp = tsens_tz_code_to_degc(last_temp, sensor_sw_id);
+ *temp = tsens_tz_code_to_degc(last_temp, sensor_sw_id, tmdev);
} else {
if (last_temp & TSENS_TM_CODE_SIGN_BIT) {
/* Sign extension for negative value */
@@ -826,38 +1433,56 @@ static void msm_tsens_get_temp(int sensor_hw_num, unsigned long *temp)
*temp = last_temp;
}
- trace_tsens_read(*temp, sensor_hw_num);
+ tmdev->sensor[sensor_hw_num].dbg_adc_code = last_temp;
+
+ trace_tsens_read(*temp, sensor_client_id);
+
+ return 0;
}
static int tsens_tz_get_temp(struct thermal_zone_device *thermal,
- unsigned long *temp)
+ int *temp)
{
struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
+ struct tsens_tm_device *tmdev = NULL;
uint32_t idx = 0;
+ int rc = 0;
- if (!tm_sensor || tm_sensor->mode != THERMAL_DEVICE_ENABLED || !temp)
+ if (!tm_sensor || !temp)
+ return -EINVAL;
+
+ tmdev = tm_sensor->tm;
+ if (!tmdev)
return -EINVAL;
- msm_tsens_get_temp(tm_sensor->sensor_hw_num, temp);
+ rc = msm_tsens_get_temp(tm_sensor->sensor_client_id, temp);
+ if (rc)
+ return rc;
idx = tmdev->sensor_dbg_info[tm_sensor->sensor_hw_num].idx;
tmdev->sensor_dbg_info[tm_sensor->sensor_hw_num].temp[idx%10] = *temp;
tmdev->sensor_dbg_info[tm_sensor->sensor_hw_num].time_stmp[idx%10] =
sched_clock();
+ tmdev->sensor_dbg_info[tm_sensor->sensor_hw_num].adccode[idx%10] =
+ tmdev->sensor[tm_sensor->sensor_hw_num].dbg_adc_code;
idx++;
tmdev->sensor_dbg_info[tm_sensor->sensor_hw_num].idx = idx;
return 0;
}
-int tsens_get_temp(struct tsens_device *device, unsigned long *temp)
+int tsens_get_temp(struct tsens_device *device, int *temp)
{
+ int rc = 0;
+
if (tsens_is_ready() <= 0) {
pr_debug("TSENS early init not done\n");
return -EPROBE_DEFER;
}
- msm_tsens_get_temp(device->sensor_num, temp);
+ rc = msm_tsens_get_temp(device->sensor_num, temp);
+ if (rc)
+ return rc;
return 0;
}
@@ -870,7 +1495,12 @@ int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors)
return -EPROBE_DEFER;
}
- *tsens_num_sensors = tmdev->tsens_num_sensor;
+ *tsens_num_sensors = 0;
+
+ if (get_all_tsens_controller_sensor_count(tsens_num_sensors) == NULL)
+ return -EINVAL;
+
+ pr_debug("%d\n", *tsens_num_sensors);
return 0;
}
@@ -941,14 +1571,24 @@ static int tsens_tm_activate_trip_type(struct thermal_zone_device *thermal,
{
struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
unsigned int reg_cntl, mask;
+ unsigned long flags;
+ struct tsens_tm_device *tmdev = NULL;
+ int rc = 0;
/* clear the interrupt and unmask */
if (!tm_sensor || trip < 0)
return -EINVAL;
+ tmdev = tm_sensor->tm;
+ if (!tmdev)
+ return -EINVAL;
+
+ spin_lock_irqsave(&tmdev->tsens_upp_low_lock, flags);
mask = (tm_sensor->sensor_hw_num);
switch (trip) {
case TSENS_TM_TRIP_CRITICAL:
+ tmdev->sensor[tm_sensor->sensor_hw_num].
+ debug_thr_state_copy.crit_th_state = mode;
reg_cntl = readl_relaxed(TSENS_TM_CRITICAL_INT_MASK
(tmdev->tsens_addr));
if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
@@ -961,6 +1601,8 @@ static int tsens_tm_activate_trip_type(struct thermal_zone_device *thermal,
(tmdev->tsens_addr)));
break;
case TSENS_TM_TRIP_WARM:
+ tmdev->sensor[tm_sensor->sensor_hw_num].
+ debug_thr_state_copy.high_th_state = mode;
reg_cntl = readl_relaxed(TSENS_TM_UPPER_LOWER_INT_MASK
(tmdev->tsens_addr));
if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
@@ -975,6 +1617,8 @@ static int tsens_tm_activate_trip_type(struct thermal_zone_device *thermal,
(tmdev->tsens_addr)));
break;
case TSENS_TM_TRIP_COOL:
+ tmdev->sensor[tm_sensor->sensor_hw_num].
+ debug_thr_state_copy.low_th_state = mode;
reg_cntl = readl_relaxed(TSENS_TM_UPPER_LOWER_INT_MASK
(tmdev->tsens_addr));
if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
@@ -985,11 +1629,14 @@ static int tsens_tm_activate_trip_type(struct thermal_zone_device *thermal,
(TSENS_TM_UPPER_LOWER_INT_MASK(tmdev->tsens_addr)));
break;
default:
- return -EINVAL;
+ rc = -EINVAL;
}
+
+ spin_unlock_irqrestore(&tmdev->tsens_upp_low_lock, flags);
/* Activate and enable the respective trip threshold setting */
mb();
- return 0;
+
+ return rc;
}
static int tsens_tz_activate_trip_type(struct thermal_zone_device *thermal,
@@ -997,10 +1644,15 @@ static int tsens_tz_activate_trip_type(struct thermal_zone_device *thermal,
{
struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
unsigned int reg_cntl, code, hi_code, lo_code, mask;
+ struct tsens_tm_device *tmdev = NULL;
if (!tm_sensor || trip < 0)
return -EINVAL;
+ tmdev = tm_sensor->tm;
+ if (!tmdev)
+ return -EINVAL;
+
lo_code = TSENS_THRESHOLD_MIN_CODE;
hi_code = TSENS_THRESHOLD_MAX_CODE;
@@ -1008,8 +1660,12 @@ static int tsens_tz_activate_trip_type(struct thermal_zone_device *thermal,
(tmdev->tsens_addr) +
(tm_sensor->sensor_hw_num *
TSENS_SN_ADDR_OFFSET)));
+
switch (trip) {
case TSENS_TRIP_WARM:
+ tmdev->sensor[tm_sensor->sensor_hw_num].
+ debug_thr_state_copy.high_th_state = mode;
+
code = (reg_cntl & TSENS_UPPER_THRESHOLD_MASK)
>> TSENS_UPPER_THRESHOLD_SHIFT;
mask = TSENS_UPPER_STATUS_CLR;
@@ -1018,6 +1674,9 @@ static int tsens_tz_activate_trip_type(struct thermal_zone_device *thermal,
lo_code = (reg_cntl & TSENS_LOWER_THRESHOLD_MASK);
break;
case TSENS_TRIP_COOL:
+ tmdev->sensor[tm_sensor->sensor_hw_num].
+ debug_thr_state_copy.low_th_state = mode;
+
code = (reg_cntl & TSENS_LOWER_THRESHOLD_MASK);
mask = TSENS_LOWER_STATUS_CLR;
@@ -1031,32 +1690,36 @@ static int tsens_tz_activate_trip_type(struct thermal_zone_device *thermal,
if (mode == THERMAL_TRIP_ACTIVATION_DISABLED)
writel_relaxed(reg_cntl | mask,
- (TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
- (tmdev->tsens_addr) +
+ (TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(tmdev->tsens_addr) +
(tm_sensor->sensor_hw_num * TSENS_SN_ADDR_OFFSET)));
- else {
+
+ else
writel_relaxed(reg_cntl & ~mask,
(TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(tmdev->tsens_addr) +
(tm_sensor->sensor_hw_num * TSENS_SN_ADDR_OFFSET)));
- }
/* Enable the thresholds */
mb();
return 0;
}
static int tsens_tm_get_trip_temp(struct thermal_zone_device *thermal,
- int trip, unsigned long *temp)
+ int trip, int *temp)
{
struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
int reg_cntl, code_mask;
+ struct tsens_tm_device *tmdev = NULL;
if (!tm_sensor || trip < 0 || !temp)
return -EINVAL;
+ tmdev = tm_sensor->tm;
+ if (!tmdev)
+ return -EINVAL;
+
switch (trip) {
case TSENS_TM_TRIP_CRITICAL:
reg_cntl = readl_relaxed((TSENS_TM_SN_CRITICAL_THRESHOLD
- (tmdev->tsens_addr)) +
+ (tmdev->tsens_addr)) +
(tm_sensor->sensor_hw_num *
TSENS_SN_ADDR_OFFSET));
if (reg_cntl & TSENS_TM_CODE_SIGN_BIT) {
@@ -1099,15 +1762,20 @@ static int tsens_tm_get_trip_temp(struct thermal_zone_device *thermal,
}
static int tsens_tz_get_trip_temp(struct thermal_zone_device *thermal,
- int trip, unsigned long *temp)
+ int trip, int *temp)
{
struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
unsigned int reg;
int sensor_sw_id = -EINVAL, rc = 0;
+ struct tsens_tm_device *tmdev = NULL;
if (!tm_sensor || trip < 0 || !temp)
return -EINVAL;
+ tmdev = tm_sensor->tm;
+ if (!tmdev)
+ return -EINVAL;
+
reg = readl_relaxed(TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR
(tmdev->tsens_addr) +
(tm_sensor->sensor_hw_num * TSENS_SN_ADDR_OFFSET));
@@ -1123,12 +1791,13 @@ static int tsens_tz_get_trip_temp(struct thermal_zone_device *thermal,
return -EINVAL;
}
- rc = tsens_get_sw_id_mapping(tm_sensor->sensor_hw_num, &sensor_sw_id);
+ rc = tsens_get_sw_id_mapping_for_controller(tm_sensor->sensor_hw_num,
+ &sensor_sw_id, tmdev);
if (rc < 0) {
pr_err("tsens mapping index not found\n");
return rc;
}
- *temp = tsens_tz_code_to_degc(reg, sensor_sw_id);
+ *temp = tsens_tz_code_to_degc(reg, sensor_sw_id, tmdev);
return 0;
}
@@ -1143,22 +1812,34 @@ static int tsens_tz_notify(struct thermal_zone_device *thermal,
}
static int tsens_tm_set_trip_temp(struct thermal_zone_device *thermal,
- int trip, unsigned long temp)
+ int trip, int temp)
{
struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
unsigned int reg_cntl;
+ unsigned long flags;
+ struct tsens_tm_device *tmdev = NULL;
+ int rc = 0;
if (!tm_sensor || trip < 0)
return -EINVAL;
+ tmdev = tm_sensor->tm;
+ if (!tmdev)
+ return -EINVAL;
+
+ spin_lock_irqsave(&tmdev->tsens_upp_low_lock, flags);
switch (trip) {
case TSENS_TM_TRIP_CRITICAL:
+ tmdev->sensor[tm_sensor->sensor_hw_num].
+ debug_thr_state_copy.crit_temp = temp;
temp &= TSENS_TM_SN_CRITICAL_THRESHOLD_MASK;
writel_relaxed(temp,
(TSENS_TM_SN_CRITICAL_THRESHOLD(tmdev->tsens_addr) +
(tm_sensor->sensor_hw_num * TSENS_SN_ADDR_OFFSET)));
break;
case TSENS_TM_TRIP_WARM:
+ tmdev->sensor[tm_sensor->sensor_hw_num].
+ debug_thr_state_copy.high_temp = temp;
reg_cntl = readl_relaxed((TSENS_TM_UPPER_LOWER_THRESHOLD
(tmdev->tsens_addr)) +
(tm_sensor->sensor_hw_num *
@@ -1171,6 +1852,8 @@ static int tsens_tm_set_trip_temp(struct thermal_zone_device *thermal,
(tm_sensor->sensor_hw_num * TSENS_SN_ADDR_OFFSET)));
break;
case TSENS_TM_TRIP_COOL:
+ tmdev->sensor[tm_sensor->sensor_hw_num].
+ debug_thr_state_copy.low_temp = temp;
reg_cntl = readl_relaxed((TSENS_TM_UPPER_LOWER_THRESHOLD
(tmdev->tsens_addr)) +
(tm_sensor->sensor_hw_num *
@@ -1182,30 +1865,38 @@ static int tsens_tm_set_trip_temp(struct thermal_zone_device *thermal,
(tm_sensor->sensor_hw_num * TSENS_SN_ADDR_OFFSET)));
break;
default:
- return -EINVAL;
+ rc = -EINVAL;
}
+ spin_unlock_irqrestore(&tmdev->tsens_upp_low_lock, flags);
/* Set trip temperature thresholds */
mb();
- return 0;
+ return rc;
}
static int tsens_tz_set_trip_temp(struct thermal_zone_device *thermal,
- int trip, unsigned long temp)
+ int trip, int temp)
{
struct tsens_tm_device_sensor *tm_sensor = thermal->devdata;
unsigned int reg_cntl;
int code, hi_code, lo_code, code_err_chk, sensor_sw_id = 0, rc = 0;
+ struct tsens_tm_device *tmdev = NULL;
if (!tm_sensor || trip < 0)
return -EINVAL;
- rc = tsens_get_sw_id_mapping(tm_sensor->sensor_hw_num, &sensor_sw_id);
+ tmdev = tm_sensor->tm;
+ if (!tmdev)
+ return -EINVAL;
+
+ rc = tsens_get_sw_id_mapping_for_controller(tm_sensor->sensor_hw_num,
+ &sensor_sw_id, tmdev);
if (rc < 0) {
pr_err("tsens mapping index not found\n");
return rc;
}
- code_err_chk = code = tsens_tz_degc_to_code(temp, sensor_sw_id);
+
+ code_err_chk = code = tsens_tz_degc_to_code(temp, sensor_sw_id, tmdev);
if (!tm_sensor || trip < 0)
return -EINVAL;
@@ -1217,12 +1908,20 @@ static int tsens_tz_set_trip_temp(struct thermal_zone_device *thermal,
TSENS_SN_ADDR_OFFSET));
switch (trip) {
case TSENS_TRIP_WARM:
+ tmdev->sensor[tm_sensor->sensor_hw_num].
+ debug_thr_state_copy.high_adc_code = code;
+ tmdev->sensor[tm_sensor->sensor_hw_num].
+ debug_thr_state_copy.high_temp = temp;
code <<= TSENS_UPPER_THRESHOLD_SHIFT;
reg_cntl &= ~TSENS_UPPER_THRESHOLD_MASK;
if (!(reg_cntl & TSENS_LOWER_STATUS_CLR))
lo_code = (reg_cntl & TSENS_LOWER_THRESHOLD_MASK);
break;
case TSENS_TRIP_COOL:
+ tmdev->sensor[tm_sensor->sensor_hw_num].
+ debug_thr_state_copy.low_adc_code = code;
+ tmdev->sensor[tm_sensor->sensor_hw_num].
+ debug_thr_state_copy.low_temp = temp;
reg_cntl &= ~TSENS_LOWER_THRESHOLD_MASK;
if (!(reg_cntl & TSENS_UPPER_STATUS_CLR))
hi_code = (reg_cntl & TSENS_UPPER_THRESHOLD_MASK)
@@ -1241,6 +1940,369 @@ static int tsens_tz_set_trip_temp(struct thermal_zone_device *thermal,
return 0;
}
+static void tsens_poll(struct work_struct *work)
+{
+ struct tsens_tm_device *tmdev = container_of(work,
+ struct tsens_tm_device, tsens_critical_poll_test.work);
+ unsigned int reg_cntl, mask, rc = 0, debug_dump, i = 0, loop = 0;
+ unsigned int debug_id = 0;
+ uint32_t r1, r2, r3, r4, offset = 0;
+ unsigned long temp, flags;
+ unsigned int status, int_mask, int_mask_val;
+ void __iomem *srot_addr;
+ void __iomem *controller_id_addr;
+ void __iomem *debug_id_addr;
+ void __iomem *debug_data_addr;
+ void __iomem *sensor_status_addr;
+ void __iomem *sensor_int_mask_addr;
+ void __iomem *sensor_critical_addr;
+
+ /* Set the Critical temperature threshold to a value of 10 that should
+ * guarantee a threshold to trigger. Check the interrupt count if
+ * it did. Schedule the next round of the above test again after
+ * 3 seconds.
+ */
+
+ controller_id_addr = TSENS_CONTROLLER_ID(tmdev->tsens_addr);
+ debug_id_addr = TSENS_DEBUG_CONTROL(tmdev->tsens_addr);
+ debug_data_addr = TSENS_DEBUG_DATA(tmdev->tsens_addr);
+ srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_addr);
+
+ temp = TSENS_DEBUG_DECIDEGC;
+ /* Sensor 0 on either of the controllers */
+ mask = 0;
+
+ reinit_completion(&tmdev->tsens_rslt_completion);
+
+ temp &= TSENS_TM_SN_CRITICAL_THRESHOLD_MASK;
+ writel_relaxed(temp,
+ (TSENS_TM_SN_CRITICAL_THRESHOLD(tmdev->tsens_addr) +
+ (mask * TSENS_SN_ADDR_OFFSET)));
+
+ tmdev->crit_timestamp_last_run = sched_clock();
+ tmdev->qtimer_val_detection_start = arch_counter_get_cntvct();
+
+ spin_lock_irqsave(&tmdev->tsens_crit_lock, flags);
+ tmdev->crit_set = true;
+ reg_cntl = readl_relaxed(TSENS_TM_CRITICAL_INT_MASK(tmdev->tsens_addr));
+ writel_relaxed(reg_cntl & ~(1 << mask),
+ (TSENS_TM_CRITICAL_INT_MASK
+ (tmdev->tsens_addr)));
+ spin_unlock_irqrestore(&tmdev->tsens_crit_lock, flags);
+
+ rc = wait_for_completion_timeout(
+ &tmdev->tsens_rslt_completion,
+ tsens_completion_timeout_hz);
+ if (!rc) {
+ pr_debug("Switch to polling, TSENS critical interrupt failed\n");
+ sensor_status_addr = TSENS_TM_SN_STATUS(tmdev->tsens_addr);
+ sensor_int_mask_addr =
+ TSENS_TM_CRITICAL_INT_MASK(tmdev->tsens_addr);
+ sensor_critical_addr =
+ TSENS_TM_SN_CRITICAL_THRESHOLD(tmdev->tsens_addr);
+
+ spin_lock_irqsave(&tmdev->tsens_crit_lock, flags);
+ if (!tmdev->crit_set) {
+ pr_debug("Ignore this check cycle\n");
+ spin_unlock_irqrestore(&tmdev->tsens_crit_lock, flags);
+ goto re_schedule;
+ }
+ status = readl_relaxed(sensor_status_addr);
+ int_mask = readl_relaxed(sensor_int_mask_addr);
+ tmdev->crit_set = false;
+ spin_unlock_irqrestore(&tmdev->tsens_crit_lock, flags);
+
+ tmdev->crit_timestamp_last_poll_request = sched_clock();
+ tmdev->qtimer_val_last_polling_check =
+ arch_counter_get_cntvct();
+ if (status & TSENS_TM_SN_STATUS_CRITICAL_STATUS) {
+
+ spin_lock_irqsave(&tmdev->tsens_crit_lock, flags);
+ int_mask = readl_relaxed(sensor_int_mask_addr);
+ int_mask_val = 1;
+ /* Mask the corresponding interrupt for the sensors */
+ writel_relaxed(int_mask | int_mask_val,
+ TSENS_TM_CRITICAL_INT_MASK(
+ tmdev->tsens_addr));
+ /* Clear the corresponding sensors interrupt */
+ writel_relaxed(int_mask_val,
+ TSENS_TM_CRITICAL_INT_CLEAR(tmdev->tsens_addr));
+ writel_relaxed(0,
+ TSENS_TM_CRITICAL_INT_CLEAR(
+ tmdev->tsens_addr));
+ spin_unlock_irqrestore(&tmdev->tsens_crit_lock, flags);
+
+ goto re_schedule;
+ }
+
+ debug_dump = readl_relaxed(controller_id_addr);
+ pr_err("Controller_id: 0x%x\n", debug_dump);
+
+ loop = 0;
+ i = 0;
+ debug_id = readl_relaxed(debug_id_addr);
+ writel_relaxed((debug_id | (i << 1) | 1),
+ TSENS_DEBUG_CONTROL(tmdev->tsens_addr));
+ while (loop < TSENS_DEBUG_LOOP_COUNT_ID_0) {
+ debug_dump = readl_relaxed(debug_data_addr);
+ r1 = readl_relaxed(debug_data_addr);
+ r2 = readl_relaxed(debug_data_addr);
+ r3 = readl_relaxed(debug_data_addr);
+ r4 = readl_relaxed(debug_data_addr);
+ pr_err("bus-id:%d value:0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
+ i, debug_dump, r1, r2, r3, r4);
+ loop++;
+ }
+
+ for (i = TSENS_DBG_BUS_ID_1; i <= TSENS_DBG_BUS_ID_15; i++) {
+ loop = 0;
+ debug_id = readl_relaxed(debug_id_addr);
+ debug_id = debug_id & TSENS_DEBUG_ID_MASK_1_4;
+ writel_relaxed((debug_id | (i << 1) | 1),
+ TSENS_DEBUG_CONTROL(tmdev->tsens_addr));
+ while (loop < TSENS_DEBUG_LOOP_COUNT) {
+ debug_dump = readl_relaxed(debug_data_addr);
+ pr_err("bus-id:%d with value: 0x%x\n",
+ i, debug_dump);
+ loop++;
+ }
+ }
+
+ pr_err("Start of TSENS TM dump\n");
+ for (i = 0; i < TSENS_DEBUG_OFFSET_RANGE; i++) {
+ r1 = readl_relaxed(controller_id_addr + offset);
+ r2 = readl_relaxed(controller_id_addr + (offset +
+ TSENS_DEBUG_OFFSET_WORD1));
+ r3 = readl_relaxed(controller_id_addr + (offset +
+ TSENS_DEBUG_OFFSET_WORD2));
+ r4 = readl_relaxed(controller_id_addr + (offset +
+ TSENS_DEBUG_OFFSET_WORD3));
+
+ pr_err("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ offset, r1, r2, r3, r4);
+ offset += TSENS_DEBUG_OFFSET_ROW;
+ }
+
+ offset = 0;
+ pr_err("Start of TSENS SROT dump\n");
+ for (i = 0; i < TSENS_DEBUG_OFFSET_RANGE; i++) {
+ r1 = readl_relaxed(srot_addr + offset);
+ r2 = readl_relaxed(srot_addr + (offset +
+ TSENS_DEBUG_OFFSET_WORD1));
+ r3 = readl_relaxed(srot_addr + (offset +
+ TSENS_DEBUG_OFFSET_WORD2));
+ r4 = readl_relaxed(srot_addr + (offset +
+ TSENS_DEBUG_OFFSET_WORD3));
+
+ pr_err("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ offset, r1, r2, r3, r4);
+ offset += TSENS_DEBUG_OFFSET_ROW;
+ }
+
+ loop = 0;
+ while (loop < TSENS_DEBUG_LOOP_COUNT) {
+ offset = TSENS_DEBUG_OFFSET_ROW *
+ TSENS_DEBUG_STATUS_REG_START;
+ pr_err("Start of TSENS TM dump %d\n", loop);
+ /* Limited dump of the registers for the temperature */
+ for (i = 0; i < TSENS_DEBUG_LOOP_COUNT; i++) {
+ r1 = readl_relaxed(controller_id_addr + offset);
+ r2 = readl_relaxed(controller_id_addr +
+ (offset + TSENS_DEBUG_OFFSET_WORD1));
+ r3 = readl_relaxed(controller_id_addr +
+ (offset + TSENS_DEBUG_OFFSET_WORD2));
+ r4 = readl_relaxed(controller_id_addr +
+ (offset + TSENS_DEBUG_OFFSET_WORD3));
+
+ pr_err("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n",
+ offset, r1, r2, r3, r4);
+ offset += TSENS_DEBUG_OFFSET_ROW;
+ }
+ loop++;
+ usleep_range(TSENS_DEBUG_MIN_CYCLE,
+ TSENS_DEBUG_MAX_CYCLE);
+ }
+
+ BUG();
+ }
+
+re_schedule:
+
+ schedule_delayed_work(&tmdev->tsens_critical_poll_test,
+ msecs_to_jiffies(tsens_sec_to_msec_value));
+}
+
+int tsens_mtc_reset_history_counter(unsigned int zone)
+{
+ unsigned int reg_cntl, is_valid;
+ void __iomem *sensor_addr;
+ struct tsens_tm_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_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);
+ }
+
+ /*Disble 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_tm_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;
+ }
+
+ if (tmdev->tsens_type == TSENS_TYPE3)
+ sensor_addr = TSENS_TM_MTC_ZONE0_SW_MASK_ADDR
+ (tmdev->tsens_addr);
+ else
+ sensor_addr = TSENS_MTC_ZONE0_SW_MASK_ADDR
+ (tmdev->tsens_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_tm_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;
+ }
+
+ if (tmdev->tsens_type == TSENS_TYPE3)
+ sensor_addr = TSENS_TM_MTC_ZONE0_LOG(tmdev->tsens_addr);
+ else
+ sensor_addr = TSENS_MTC_ZONE0_LOG(tmdev->tsens_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_tm_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_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);
+
static struct thermal_zone_device_ops tsens_thermal_zone_ops = {
.get_temp = tsens_tz_get_temp,
.get_mode = tsens_tz_get_mode,
@@ -1264,51 +2326,72 @@ static struct thermal_zone_device_ops tsens_tm_thermal_zone_ops = {
static irqreturn_t tsens_tm_critical_irq_thread(int irq, void *data)
{
struct tsens_tm_device *tm = data;
- unsigned int i, status, threshold;
+ unsigned int i, status;
+ unsigned long flags;
void __iomem *sensor_status_addr;
void __iomem *sensor_int_mask_addr;
void __iomem *sensor_critical_addr;
int sensor_sw_id = -EINVAL, rc = 0;
- sensor_status_addr = TSENS_TM_SN_STATUS(tmdev->tsens_addr);
+ tm->crit_set = false;
+ sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_addr);
sensor_int_mask_addr =
- TSENS_TM_CRITICAL_INT_MASK(tmdev->tsens_addr);
+ TSENS_TM_CRITICAL_INT_MASK(tm->tsens_addr);
sensor_critical_addr =
- TSENS_TM_SN_CRITICAL_THRESHOLD(tmdev->tsens_addr);
+ TSENS_TM_SN_CRITICAL_THRESHOLD(tm->tsens_addr);
for (i = 0; i < tm->tsens_num_sensor; i++) {
bool critical_thr = false;
int int_mask, int_mask_val;
uint32_t addr_offset;
+ spin_lock_irqsave(&tm->tsens_crit_lock, flags);
addr_offset = tm->sensor[i].sensor_hw_num *
TSENS_SN_ADDR_OFFSET;
status = readl_relaxed(sensor_status_addr + addr_offset);
- if (status & TSENS_TM_SN_STATUS_CRITICAL_STATUS) {
+ int_mask = readl_relaxed(sensor_int_mask_addr);
+
+ if ((status & TSENS_TM_SN_STATUS_CRITICAL_STATUS) &&
+ !(int_mask & (1 << tm->sensor[i].sensor_hw_num))) {
int_mask = readl_relaxed(sensor_int_mask_addr);
int_mask_val = (1 << tm->sensor[i].sensor_hw_num);
+ /* Mask the corresponding interrupt for the sensors */
writel_relaxed(int_mask | int_mask_val,
TSENS_TM_CRITICAL_INT_MASK(
- tmdev->tsens_addr));
+ tm->tsens_addr));
+ /* Clear the corresponding sensors interrupt */
+ writel_relaxed(int_mask_val,
+ TSENS_TM_CRITICAL_INT_CLEAR(tm->tsens_addr));
+ writel_relaxed(0,
+ TSENS_TM_CRITICAL_INT_CLEAR(
+ tm->tsens_addr));
critical_thr = true;
+ tm->sensor[i].debug_thr_state_copy.
+ crit_th_state = THERMAL_DEVICE_DISABLED;
}
+ spin_unlock_irqrestore(&tm->tsens_crit_lock, flags);
+
if (critical_thr) {
- unsigned long temp;
- tsens_tz_get_temp(tm->sensor[i].tz_dev, &temp);
+ int temp;
- rc = tsens_get_sw_id_mapping(
+ tsens_tz_get_temp(tm->sensor[i].tz_dev, &temp);
+ rc = tsens_get_sw_id_mapping_for_controller(
tm->sensor[i].sensor_hw_num,
- &sensor_sw_id);
+ &sensor_sw_id, tm);
if (rc < 0)
pr_err("tsens mapping index not found\n");
- pr_debug("sensor:%d trigger temp (%d degC)\n",
+ pr_debug("sensor:%d trigger temp (%d degC) with count:%d\n",
tm->sensor[i].sensor_hw_num,
- (status & TSENS_TM_SN_LAST_TEMP_MASK));
- threshold = readl_relaxed(sensor_critical_addr +
- addr_offset);
+ (status & TSENS_TM_SN_LAST_TEMP_MASK),
+ tm->tsens_critical_irq_cnt);
+ tm->tsens_critical_irq_cnt++;
}
}
+ tm->crit_timestamp_last_interrupt_handled = sched_clock();
+ tm->qtimer_val_last_detection_interrupt = arch_counter_get_cntvct();
+
+ complete(&tm->tsens_rslt_completion);
/* Mask critical interrupt */
mb();
@@ -1319,73 +2402,110 @@ static irqreturn_t tsens_tm_irq_thread(int irq, void *data)
{
struct tsens_tm_device *tm = data;
unsigned int i, status, threshold;
+ unsigned long flags;
void __iomem *sensor_status_addr;
void __iomem *sensor_int_mask_addr;
void __iomem *sensor_upper_lower_addr;
int sensor_sw_id = -EINVAL, rc = 0;
+ uint32_t addr_offset;
- sensor_status_addr = TSENS_TM_SN_STATUS(tmdev->tsens_addr);
+ sensor_status_addr = TSENS_TM_SN_STATUS(tm->tsens_addr);
sensor_int_mask_addr =
- TSENS_TM_UPPER_LOWER_INT_MASK(tmdev->tsens_addr);
+ TSENS_TM_UPPER_LOWER_INT_MASK(tm->tsens_addr);
sensor_upper_lower_addr =
- TSENS_TM_UPPER_LOWER_THRESHOLD(tmdev->tsens_addr);
+ TSENS_TM_UPPER_LOWER_THRESHOLD(tm->tsens_addr);
for (i = 0; i < tm->tsens_num_sensor; i++) {
bool upper_thr = false, lower_thr = false;
- int int_mask, int_mask_val;
- uint32_t addr_offset;
+ int int_mask, int_mask_val = 0;
+ spin_lock_irqsave(&tm->tsens_upp_low_lock, flags);
addr_offset = tm->sensor[i].sensor_hw_num *
TSENS_SN_ADDR_OFFSET;
status = readl_relaxed(sensor_status_addr + addr_offset);
- if (status & TSENS_TM_SN_STATUS_UPPER_STATUS) {
+ threshold = readl_relaxed(sensor_upper_lower_addr +
+ addr_offset);
+ int_mask = readl_relaxed(sensor_int_mask_addr);
+
+ if ((status & TSENS_TM_SN_STATUS_UPPER_STATUS) &&
+ !(int_mask &
+ (1 << (tm->sensor[i].sensor_hw_num + 16)))) {
int_mask = readl_relaxed(sensor_int_mask_addr);
int_mask_val = TSENS_TM_UPPER_INT_SET(
tm->sensor[i].sensor_hw_num);
+ /* Mask the corresponding interrupt for the sensors */
writel_relaxed(int_mask | int_mask_val,
TSENS_TM_UPPER_LOWER_INT_MASK(
- tmdev->tsens_addr));
+ tm->tsens_addr));
+ /* Clear the corresponding sensors interrupt */
+ writel_relaxed(int_mask_val,
+ TSENS_TM_UPPER_LOWER_INT_CLEAR(
+ tm->tsens_addr));
+ writel_relaxed(0,
+ TSENS_TM_UPPER_LOWER_INT_CLEAR(
+ tm->tsens_addr));
upper_thr = true;
+ tm->sensor[i].debug_thr_state_copy.
+ high_th_state = THERMAL_DEVICE_DISABLED;
}
- if (status & TSENS_TM_SN_STATUS_LOWER_STATUS) {
+
+ if ((status & TSENS_TM_SN_STATUS_LOWER_STATUS) &&
+ !(int_mask &
+ (1 << tm->sensor[i].sensor_hw_num))) {
int_mask = readl_relaxed(sensor_int_mask_addr);
int_mask_val = (1 << tm->sensor[i].sensor_hw_num);
+ /* Mask the corresponding interrupt for the sensors */
writel_relaxed(int_mask | int_mask_val,
TSENS_TM_UPPER_LOWER_INT_MASK(
- tmdev->tsens_addr));
+ tm->tsens_addr));
+ /* Clear the corresponding sensors interrupt */
+ writel_relaxed(int_mask_val,
+ TSENS_TM_UPPER_LOWER_INT_CLEAR(
+ tm->tsens_addr));
+ writel_relaxed(0,
+ TSENS_TM_UPPER_LOWER_INT_CLEAR(
+ tm->tsens_addr));
lower_thr = true;
+ tm->sensor[i].debug_thr_state_copy.
+ low_th_state = THERMAL_DEVICE_DISABLED;
}
+ spin_unlock_irqrestore(&tm->tsens_upp_low_lock, flags);
+
if (upper_thr || lower_thr) {
- unsigned long temp;
+ int temp;
enum thermal_trip_type trip =
THERMAL_TRIP_CONFIGURABLE_LOW;
if (upper_thr)
trip = THERMAL_TRIP_CONFIGURABLE_HI;
tsens_tz_get_temp(tm->sensor[i].tz_dev, &temp);
+ thermal_sensor_trip(tm->sensor[i].tz_dev, trip, temp);
- rc = tsens_get_sw_id_mapping(
+ rc = tsens_get_sw_id_mapping_for_controller(
tm->sensor[i].sensor_hw_num,
- &sensor_sw_id);
+ &sensor_sw_id, tm);
if (rc < 0)
- pr_err("tsens mapping index not found\n");
+ pr_debug("tsens mapping index not found\n");
+ /* Use sensor_client_id for multiple controllers */
pr_debug("sensor:%d trigger temp (%d degC)\n",
- tm->sensor[i].sensor_hw_num,
+ tm->sensor[i].sensor_client_id,
(status & TSENS_TM_SN_LAST_TEMP_MASK));
- threshold = readl_relaxed(sensor_upper_lower_addr +
- addr_offset);
- if (upper_thr)
+ if (upper_thr) {
trace_tsens_threshold_hit(
TSENS_TM_UPPER_THRESHOLD_VALUE(
threshold),
- tm->sensor[i].sensor_hw_num);
- else
+ tm->sensor[i].sensor_client_id);
+ tm->tsens_upper_irq_cnt++;
+ } else {
trace_tsens_threshold_clear(
TSENS_TM_LOWER_THRESHOLD_VALUE(
threshold),
- tm->sensor[i].sensor_hw_num);
+ tm->sensor[i].sensor_client_id);
+ tm->tsens_lower_irq_cnt++;
+ }
}
}
+
/* Disable monitoring sensor trip threshold for triggered sensor */
mb();
@@ -1398,20 +2518,22 @@ static irqreturn_t tsens_irq_thread(int irq, void *data)
unsigned int i, status, threshold;
void __iomem *sensor_status_addr;
void __iomem *sensor_status_ctrl_addr;
- int sensor_sw_id = -EINVAL, rc = 0;
+ int sensor_sw_id = -EINVAL;
uint32_t idx = 0;
- if (tmdev->tsens_type == TSENS_TYPE2)
- sensor_status_addr = TSENS2_SN_STATUS_ADDR(tmdev->tsens_addr);
+ if ((tm->tsens_type == TSENS_TYPE2) ||
+ (tm->tsens_type == TSENS_TYPE4))
+ sensor_status_addr = TSENS2_SN_STATUS_ADDR(tm->tsens_addr);
else
- sensor_status_addr = TSENS_S0_STATUS_ADDR(tmdev->tsens_addr);
+ sensor_status_addr = TSENS_S0_STATUS_ADDR(tm->tsens_addr);
sensor_status_ctrl_addr =
- TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(tmdev->tsens_addr);
+ TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(tm->tsens_addr);
for (i = 0; i < tm->tsens_num_sensor; i++) {
bool upper_thr = false, lower_thr = false;
uint32_t addr_offset;
+ sensor_sw_id = tm->sensor[i].sensor_sw_id;
addr_offset = tm->sensor[i].sensor_hw_num *
TSENS_SN_ADDR_OFFSET;
status = readl_relaxed(sensor_status_addr + addr_offset);
@@ -1420,72 +2542,743 @@ static irqreturn_t tsens_irq_thread(int irq, void *data)
if (status & TSENS_SN_STATUS_UPPER_STATUS) {
writel_relaxed(threshold | TSENS_UPPER_STATUS_CLR,
TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(
- tmdev->tsens_addr + addr_offset));
+ tm->tsens_addr + addr_offset));
upper_thr = true;
+ tm->sensor[i].debug_thr_state_copy.
+ high_th_state = THERMAL_DEVICE_DISABLED;
}
if (status & TSENS_SN_STATUS_LOWER_STATUS) {
writel_relaxed(threshold | TSENS_LOWER_STATUS_CLR,
TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(
- tmdev->tsens_addr + addr_offset));
+ tm->tsens_addr + addr_offset));
lower_thr = true;
+ tm->sensor[i].debug_thr_state_copy.
+ low_th_state = THERMAL_DEVICE_DISABLED;
}
if (upper_thr || lower_thr) {
- unsigned long temp;
+ int temp;
enum thermal_trip_type trip =
THERMAL_TRIP_CONFIGURABLE_LOW;
if (upper_thr)
trip = THERMAL_TRIP_CONFIGURABLE_HI;
tsens_tz_get_temp(tm->sensor[i].tz_dev, &temp);
+ thermal_sensor_trip(tm->sensor[i].tz_dev, trip, temp);
- rc = tsens_get_sw_id_mapping(
- tm->sensor[i].sensor_hw_num,
- &sensor_sw_id);
- if (rc < 0)
- pr_err("tsens mapping index not found\n");
pr_debug("sensor:%d trigger temp (%d degC)\n",
tm->sensor[i].sensor_hw_num,
tsens_tz_code_to_degc((status &
TSENS_SN_STATUS_TEMP_MASK),
- sensor_sw_id));
+ tm->sensor[i].sensor_sw_id, tm));
if (upper_thr)
trace_tsens_threshold_hit(
tsens_tz_code_to_degc((threshold &
TSENS_UPPER_THRESHOLD_MASK) >>
TSENS_UPPER_THRESHOLD_SHIFT,
- sensor_sw_id),
+ sensor_sw_id, tm),
tm->sensor[i].sensor_hw_num);
else
trace_tsens_threshold_clear(
tsens_tz_code_to_degc((threshold &
TSENS_LOWER_THRESHOLD_MASK),
- sensor_sw_id),
+ sensor_sw_id, tm),
tm->sensor[i].sensor_hw_num);
}
}
/* debug */
- idx = tmdev->tsens_thread_iq_dbg.idx;
- tmdev->tsens_thread_iq_dbg.dbg_count[idx%10]++;
- tmdev->tsens_thread_iq_dbg.time_stmp[idx%10] = sched_clock();
- tmdev->tsens_thread_iq_dbg.idx++;
+ idx = tm->tsens_thread_iq_dbg.idx;
+ tm->tsens_thread_iq_dbg.dbg_count[idx%10]++;
+ tm->tsens_thread_iq_dbg.time_stmp[idx%10] = sched_clock();
+ tm->tsens_thread_iq_dbg.idx++;
+ /* Disable monitoring sensor trip threshold for triggered sensor */
mb();
return IRQ_HANDLED;
}
-static void tsens_hw_init(void)
+static int tsens_hw_init(struct tsens_tm_device *tmdev)
{
- if (tmdev->tsens_type == TSENS_TYPE3)
+ void __iomem *srot_addr;
+ unsigned int srot_val;
+
+ if (!tmdev) {
+ pr_err("Invalid tsens device\n");
+ return -EINVAL;
+ }
+
+ if (tmdev->tsens_type == TSENS_TYPE3) {
+ srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_addr + 0x4);
+ srot_val = readl_relaxed(srot_addr);
+ if (!(srot_val & TSENS_EN)) {
+ pr_err("TSENS device is not enabled\n");
+ return -ENODEV;
+ }
writel_relaxed(TSENS_TM_CRITICAL_INT_EN |
TSENS_TM_UPPER_INT_EN | TSENS_TM_LOWER_INT_EN,
TSENS_TM_INT_EN(tmdev->tsens_addr));
- else
+ } else
writel_relaxed(TSENS_INTERRUPT_EN,
TSENS_UPPER_LOWER_INTERRUPT_CTRL(tmdev->tsens_addr));
+
+ return 0;
+}
+
+static int tsens_calib_msm8937_msmgold_sensors(struct tsens_tm_device *tmdev)
+{
+ int i, tsens_base0_data = 0, tsens_base1_data = 0, ext_sen = 1;
+ int tsens0_point1 = 0, tsens0_point2 = 0;
+ int tsens1_point1 = 0, tsens1_point2 = 0;
+ int tsens2_point1 = 0, tsens2_point2 = 0;
+ int tsens3_point1 = 0, tsens3_point2 = 0;
+ int tsens4_point1 = 0, tsens4_point2 = 0;
+ int tsens5_point1 = 0, tsens5_point2 = 0;
+ int tsens6_point1 = 0, tsens6_point2 = 0;
+ int tsens7_point1 = 0, tsens7_point2 = 0;
+ int tsens8_point1 = 0, tsens8_point2 = 0;
+ int tsens9_point1 = 0, tsens9_point2 = 0;
+ int tsens10_point1 = 0, tsens10_point2 = 0;
+
+ int tsens_calibration_mode = 0, temp = 0;
+ uint32_t calib_data[5] = {0, 0, 0, 0, 0};
+ uint32_t calib_tsens_point1_data[11], calib_tsens_point2_data[11];
+
+ if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_MSMGOLD)
+ ext_sen = 0;
+
+ if (!tmdev->calibration_less_mode) {
+
+ calib_data[0] = readl_relaxed(tmdev->tsens_calib_addr + 0x1D8);
+ calib_data[1] = readl_relaxed(tmdev->tsens_calib_addr + 0x1DC);
+ calib_data[2] = readl_relaxed(tmdev->tsens_calib_addr + 0x210);
+ calib_data[3] = readl_relaxed(tmdev->tsens_calib_addr + 0x214);
+ calib_data[4] = readl_relaxed(tmdev->tsens_calib_addr + 0x230);
+
+ tsens_calibration_mode =
+ (calib_data[2] &
+ TSENS_CONTR_14_TSENS_CAL_SEL);
+
+ pr_debug("calib mode is %d\n", tsens_calibration_mode);
+ }
+
+ if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB) ||
+ (tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) {
+ tsens_base0_data = (calib_data[0] &
+ TSENS_CONTR_14_BASE0_MASK);
+ tsens0_point1 = (calib_data[2] &
+ TSENS0_CONTR_14_POINT1_MASK)
+ >> TSENS0_CONTR_14_POINT1_SHIFT;
+ tsens1_point1 = (calib_data[2] &
+ TSENS1_CONTR_14_POINT1_MASK)
+ >> TSENS1_CONTR_14_POINT1_SHIFT;
+ tsens2_point1 = (calib_data[2] &
+ TSENS2_CONTR_14_POINT1_MASK_0_4)
+ >> TSENS2_CONTR_14_POINT1_SHIFT_0_4;
+ temp = (calib_data[3] & TSENS2_CONTR_14_POINT1_MASK_5)
+ << TSENS2_CONTR_14_POINT1_SHIFT_5;
+ tsens2_point1 |= temp;
+ tsens3_point1 = (calib_data[3] &
+ TSENS3_CONTR_14_POINT1_MASK)
+ >> TSENS3_CONTR_14_POINT1_SHIFT;
+ tsens4_point1 = (calib_data[3] &
+ TSENS4_CONTR_14_POINT1_MASK)
+ >> TSENS4_CONTR_14_POINT1_SHIFT;
+ tsens5_point1 = (calib_data[0] &
+ TSENS5_CONTR_14_POINT1_MASK)
+ >> TSENS5_CONTR_14_POINT1_SHIFT;
+ tsens6_point1 = (calib_data[0] &
+ TSENS6_CONTR_14_POINT1_MASK)
+ >> TSENS6_CONTR_14_POINT1_SHIFT;
+ tsens7_point1 = (calib_data[1] &
+ TSENS7_CONTR_14_POINT1_MASK);
+ tsens8_point1 = (calib_data[1] &
+ TSENS8_CONTR_14_POINT1_MASK)
+ >> TSENS8_CONTR_14_POINT1_SHIFT;
+ tsens9_point1 = (calib_data[4] &
+ TSENS9_CONTR_14_POINT1_MASK);
+ if (ext_sen)
+ tsens10_point1 = (calib_data[4] &
+ TSENS10_CONTR_14_POINT1_MASK)
+ >> TSENS10_CONTR_14_POINT1_SHIFT;
+ }
+
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ tsens_base1_data = (calib_data[1] &
+ TSENS_CONTR_14_BASE1_MASK)
+ >> TSENS_CONTR_14_BASE1_SHIFT;
+ tsens0_point2 = (calib_data[2] &
+ TSENS0_CONTR_14_POINT2_MASK)
+ >> TSENS0_CONTR_14_POINT2_SHIFT;
+ tsens1_point2 = (calib_data[2] &
+ TSENS1_CONTR_14_POINT2_MASK)
+ >> TSENS1_CONTR_14_POINT2_SHIFT;
+ tsens2_point2 = (calib_data[3] &
+ TSENS2_CONTR_14_POINT2_MASK)
+ >> TSENS2_CONTR_14_POINT2_SHIFT;
+ tsens3_point2 = (calib_data[3] &
+ TSENS3_CONTR_14_POINT2_MASK)
+ >> TSENS3_CONTR_14_POINT2_SHIFT;
+ tsens4_point2 = (calib_data[3] &
+ TSENS4_CONTR_14_POINT2_MASK)
+ >> TSENS4_CONTR_14_POINT2_SHIFT;
+ tsens5_point2 = (calib_data[0] &
+ TSENS5_CONTR_14_POINT2_MASK)
+ >> TSENS5_CONTR_14_POINT2_SHIFT;
+ tsens6_point2 = (calib_data[0] &
+ TSENS6_CONTR_14_POINT2_MASK)
+ >> TSENS6_CONTR_14_POINT2_SHIFT;
+ tsens7_point2 = (calib_data[1] &
+ TSENS7_CONTR_14_POINT2_MASK)
+ >> TSENS7_CONTR_14_POINT2_SHIFT;
+ tsens8_point2 = (calib_data[1] &
+ TSENS8_CONTR_14_POINT2_MASK)
+ >> TSENS8_CONTR_14_POINT2_SHIFT;
+ tsens9_point2 = (calib_data[4] &
+ TSENS9_CONTR_14_POINT2_MASK)
+ >> TSENS9_CONTR_14_POINT2_SHIFT;
+ if (ext_sen)
+ tsens10_point2 = (calib_data[4] &
+ TSENS10_CONTR_14_POINT2_MASK)
+ >> TSENS10_CONTR_14_POINT2_SHIFT;
+ }
+
+ if (tsens_calibration_mode == 0) {
+ pr_debug("TSENS in calibrationless mode\n");
+ for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+ calib_tsens_point2_data[i] = TSENS_NO_CALIB_POINT2_DATA;
+ calib_tsens_point1_data[i] = TSENS_NO_CALIB_POINT1_DATA;
+ }
+ }
+
+ if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) ||
+ (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
+ calib_tsens_point1_data[0] =
+ (((tsens_base0_data) + tsens0_point1) << 2) +
+ tmdev->sensor[0].wa_temp1_calib_offset_factor;
+ calib_tsens_point1_data[1] =
+ (((tsens_base0_data) + tsens1_point1) << 2) +
+ tmdev->sensor[1].wa_temp1_calib_offset_factor;
+ calib_tsens_point1_data[2] =
+ (((tsens_base0_data) + tsens2_point1) << 2) +
+ tmdev->sensor[2].wa_temp1_calib_offset_factor;
+ calib_tsens_point1_data[3] =
+ (((tsens_base0_data) + tsens3_point1) << 2) +
+ tmdev->sensor[3].wa_temp1_calib_offset_factor;
+ calib_tsens_point1_data[4] =
+ (((tsens_base0_data) + tsens4_point1) << 2) +
+ tmdev->sensor[4].wa_temp1_calib_offset_factor;
+ calib_tsens_point1_data[5] =
+ (((tsens_base0_data) + tsens5_point1) << 2) +
+ tmdev->sensor[5].wa_temp1_calib_offset_factor;
+ calib_tsens_point1_data[6] =
+ (((tsens_base0_data) + tsens6_point1) << 2) +
+ tmdev->sensor[6].wa_temp1_calib_offset_factor;
+ calib_tsens_point1_data[7] =
+ (((tsens_base0_data) + tsens7_point1) << 2) +
+ tmdev->sensor[7].wa_temp1_calib_offset_factor;
+ calib_tsens_point1_data[8] =
+ (((tsens_base0_data) + tsens8_point1) << 2) +
+ tmdev->sensor[8].wa_temp1_calib_offset_factor;
+ calib_tsens_point1_data[9] =
+ (((tsens_base0_data) + tsens9_point1) << 2) +
+ tmdev->sensor[9].wa_temp1_calib_offset_factor;
+ if (ext_sen)
+ calib_tsens_point1_data[10] =
+ (((tsens_base0_data) + tsens10_point1) << 2) +
+ tmdev->sensor[10].wa_temp1_calib_offset_factor;
+ }
+
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ pr_debug("two point calibration calculation\n");
+ calib_tsens_point2_data[0] =
+ ((tsens_base1_data + tsens0_point2) << 2) +
+ tmdev->sensor[0].wa_temp2_calib_offset_factor;
+ calib_tsens_point2_data[1] =
+ ((tsens_base1_data + tsens1_point2) << 2) +
+ tmdev->sensor[1].wa_temp2_calib_offset_factor;
+ calib_tsens_point2_data[2] =
+ ((tsens_base1_data + tsens2_point2) << 2) +
+ tmdev->sensor[2].wa_temp2_calib_offset_factor;
+ calib_tsens_point2_data[3] =
+ ((tsens_base1_data + tsens3_point2) << 2) +
+ tmdev->sensor[3].wa_temp2_calib_offset_factor;
+ calib_tsens_point2_data[4] =
+ ((tsens_base1_data + tsens4_point2) << 2) +
+ tmdev->sensor[4].wa_temp2_calib_offset_factor;
+ calib_tsens_point2_data[5] =
+ ((tsens_base1_data + tsens5_point2) << 2) +
+ tmdev->sensor[5].wa_temp2_calib_offset_factor;
+ calib_tsens_point2_data[6] =
+ ((tsens_base1_data + tsens6_point2) << 2) +
+ tmdev->sensor[6].wa_temp2_calib_offset_factor;
+ calib_tsens_point2_data[7] =
+ ((tsens_base1_data + tsens7_point2) << 2) +
+ tmdev->sensor[7].wa_temp2_calib_offset_factor;
+ calib_tsens_point2_data[8] =
+ ((tsens_base1_data + tsens8_point2) << 2) +
+ tmdev->sensor[8].wa_temp2_calib_offset_factor;
+ calib_tsens_point2_data[9] =
+ ((tsens_base1_data + tsens9_point2) << 2) +
+ tmdev->sensor[9].wa_temp2_calib_offset_factor;
+ if (ext_sen)
+ calib_tsens_point2_data[10] =
+ ((tsens_base1_data + tsens10_point2) << 2) +
+ tmdev->sensor[10].wa_temp2_calib_offset_factor;
+ }
+
+ for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+ int32_t num = 0, den = 0;
+
+ tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
+ tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
+ pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
+ i, tmdev->sensor[i].calib_data_point1,
+ tmdev->sensor[i].calib_data_point2);
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ /*
+ * slope (m) = adc_code2 - adc_code1 (y2 - y1)
+ * temp_120_degc - temp_30_degc (x2 - x1)
+ */
+ num = tmdev->sensor[i].calib_data_point2 -
+ tmdev->sensor[i].calib_data_point1;
+ num *= tmdev->tsens_factor;
+ den = TSENS_CAL_DEGC_POINT2 - TSENS_CAL_DEGC_POINT1;
+ tmdev->sensor[i].slope_mul_tsens_factor = num/den;
+ }
+ tmdev->sensor[i].offset = (tmdev->sensor[i].calib_data_point1 *
+ tmdev->tsens_factor) - (TSENS_CAL_DEGC_POINT1 *
+ tmdev->sensor[i].slope_mul_tsens_factor);
+ pr_debug("offset:%d and slope:%d\n", tmdev->sensor[i].offset,
+ tmdev->sensor[i].slope_mul_tsens_factor);
+ tmdev->prev_reading_avail = false;
+ }
+ return 0;
+}
+
+static int tsens_calib_mdm9607_sensors(struct tsens_tm_device *tmdev)
+{
+ int i, tsens_base0_data = 0, tsens_base1_data = 0;
+ int tsens0_point1 = 0, tsens0_point2 = 0;
+ int tsens1_point1 = 0, tsens1_point2 = 0;
+ int tsens2_point1 = 0, tsens2_point2 = 0;
+ int tsens3_point1 = 0, tsens3_point2 = 0;
+ int tsens4_point1 = 0, tsens4_point2 = 0;
+ int tsens_calibration_mode = 0;
+ uint32_t calib_data[3] = {0, 0, 0};
+ uint32_t calib_tsens_point1_data[5], calib_tsens_point2_data[5];
+
+ if (!tmdev->calibration_less_mode) {
+ calib_data[0] = readl_relaxed(tmdev->tsens_calib_addr + 0x228);
+ calib_data[1] = readl_relaxed(tmdev->tsens_calib_addr + 0x22c);
+ calib_data[2] = readl_relaxed(tmdev->tsens_calib_addr + 0x230);
+
+ tsens_calibration_mode =
+ (calib_data[2] & TSENS_MDM9607_TSENS_CAL_SEL) >>
+ TSENS_MDM9607_CAL_SEL_SHIFT;
+
+ pr_debug("calib mode is %d\n", tsens_calibration_mode);
+ }
+
+ if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB) ||
+ (tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) {
+ tsens_base0_data =
+ (calib_data[0] & TSENS_MDM9607_BASE0_MASK);
+ tsens0_point1 = (calib_data[0] & TSENS0_MDM9607_POINT1_MASK)
+ >> TSENS0_MDM9607_POINT1_SHIFT;
+ tsens1_point1 = (calib_data[0] & TSENS1_MDM9607_POINT1_MASK)
+ >> TSENS1_MDM9607_POINT1_SHIFT;
+ tsens2_point1 = (calib_data[1] & TSENS2_MDM9607_POINT1_MASK);
+ tsens3_point1 = (calib_data[1] & TSENS3_MDM9607_POINT1_MASK)
+ >> TSENS3_MDM9607_POINT1_SHIFT;
+ tsens4_point1 = (calib_data[2] & TSENS4_MDM9607_POINT1_MASK);
+ }
+
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ tsens_base1_data = (calib_data[2] & TSENS_MDM9607_BASE1_MASK)
+ >> TSENS_MDM9607_BASE1_SHIFT;
+ tsens0_point2 = (calib_data[0] & TSENS0_MDM9607_POINT2_MASK)
+ >> TSENS0_MDM9607_POINT2_SHIFT;
+ tsens1_point2 = (calib_data[0] & TSENS1_MDM9607_POINT2_MASK)
+ >> TSENS1_MDM9607_POINT2_SHIFT;
+ tsens2_point2 = (calib_data[1] & TSENS2_MDM9607_POINT2_MASK)
+ >> TSENS2_MDM9607_POINT2_SHIFT;
+ tsens3_point2 = (calib_data[1] & TSENS3_MDM9607_POINT2_MASK)
+ >> TSENS3_MDM9607_POINT2_SHIFT;
+ tsens4_point2 = (calib_data[2] & TSENS4_MDM9607_POINT2_MASK)
+ >> TSENS4_MDM9607_POINT2_SHIFT;
+ }
+
+ if (tsens_calibration_mode == 0) {
+ pr_debug("TSENS in calibrationless mode\n");
+ for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+ calib_tsens_point2_data[i] = TSENS_NO_CALIB_POINT2_DATA;
+ calib_tsens_point1_data[i] = TSENS_NO_CALIB_POINT1_DATA;
+ }
+ }
+
+ if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) ||
+ (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
+ calib_tsens_point1_data[0] =
+ (((tsens_base0_data) + tsens0_point1) << 2);
+ calib_tsens_point1_data[1] =
+ (((tsens_base0_data) + tsens1_point1) << 2);
+ calib_tsens_point1_data[2] =
+ (((tsens_base0_data) + tsens2_point1) << 2);
+ calib_tsens_point1_data[3] =
+ (((tsens_base0_data) + tsens3_point1) << 2);
+ calib_tsens_point1_data[4] =
+ (((tsens_base0_data) + tsens4_point1) << 2);
+ }
+
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ pr_debug("two point calibration calculation\n");
+ calib_tsens_point2_data[0] =
+ ((tsens_base1_data + tsens0_point2) << 2);
+ calib_tsens_point2_data[1] =
+ ((tsens_base1_data + tsens1_point2) << 2);
+ calib_tsens_point2_data[2] =
+ ((tsens_base1_data + tsens2_point2) << 2);
+ calib_tsens_point2_data[3] =
+ ((tsens_base1_data + tsens3_point2) << 2);
+ calib_tsens_point2_data[4] =
+ ((tsens_base1_data + tsens4_point2) << 2);
+ }
+
+ for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+ int32_t num = 0, den = 0;
+
+ tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
+ tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
+ pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
+ i, tmdev->sensor[i].calib_data_point1,
+ tmdev->sensor[i].calib_data_point2);
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ /*
+ * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
+ * temp_120_degc - temp_30_degc (x2 - x1)
+ */
+ num = tmdev->sensor[i].calib_data_point2 -
+ tmdev->sensor[i].calib_data_point1;
+ num *= tmdev->tsens_factor;
+ den = TSENS_CAL_DEGC_POINT2 - TSENS_CAL_DEGC_POINT1;
+ tmdev->sensor[i].slope_mul_tsens_factor = num/den;
+ }
+ tmdev->sensor[i].offset = (tmdev->sensor[i].calib_data_point1 *
+ tmdev->tsens_factor) - (TSENS_CAL_DEGC_POINT1 *
+ tmdev->sensor[i].slope_mul_tsens_factor);
+ pr_debug("offset:%d and slope:%d\n", tmdev->sensor[i].offset,
+ tmdev->sensor[i].slope_mul_tsens_factor);
+ tmdev->prev_reading_avail = false;
+ }
+
+ return 0;
+}
+
+static int tsens_calib_msm8952_sensors(struct tsens_tm_device *tmdev)
+{
+ int i, tsens_base0_data = 0, tsens_base1_data = 0;
+ int tsens0_point1 = 0, tsens0_point2 = 0;
+ int tsens1_point1 = 0, tsens1_point2 = 0;
+ int tsens2_point1 = 0, tsens2_point2 = 0;
+ int tsens3_point1 = 0, tsens3_point2 = 0;
+ int tsens4_point1 = 0, tsens4_point2 = 0;
+ int tsens5_point1 = 0, tsens5_point2 = 0;
+ int tsens6_point1 = 0, tsens6_point2 = 0;
+ int tsens7_point1 = 0, tsens7_point2 = 0;
+ int tsens8_point1 = 0, tsens8_point2 = 0;
+ int tsens9_point1 = 0, tsens9_point2 = 0;
+ int tsens10_point1 = 0, tsens10_point2 = 0;
+
+ int tsens_calibration_mode = 0, temp = 0;
+ uint32_t calib_data[5] = {0, 0, 0, 0, 0};
+ uint32_t calib_tsens_point1_data[11], calib_tsens_point2_data[11];
+
+ if (!tmdev->calibration_less_mode) {
+ calib_data[0] = readl_relaxed(
+ TSENS_8939_EEPROM
+ (tmdev->tsens_calib_addr) + 0x30);
+ calib_data[1] = readl_relaxed(
+ (TSENS_8939_EEPROM
+ (tmdev->tsens_calib_addr) + 0x34));
+ calib_data[2] = readl_relaxed(
+ (TSENS_8939_EEPROM
+ (tmdev->tsens_calib_addr)));
+ calib_data[3] = readl_relaxed(
+ (TSENS_8939_EEPROM
+ (tmdev->tsens_calib_addr) + 0x4));
+ calib_data[4] = readl_relaxed(
+ (TSENS_8939_EEPROM
+ (tmdev->tsens_calib_addr) + 0x50));
+
+ tsens_calibration_mode =
+ (calib_data[0] &
+ TSENS_CONTR_14_TSENS_CAL_SEL);
+
+ pr_debug("calib mode is %d\n", tsens_calibration_mode);
+ }
+
+ if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB) ||
+ (tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) {
+ tsens_base0_data = (calib_data[2] &
+ TSENS_CONTR_14_BASE0_MASK);
+ tsens0_point1 = (calib_data[0] &
+ TSENS0_CONTR_14_POINT1_MASK)
+ >> TSENS0_CONTR_14_POINT1_SHIFT;
+ tsens1_point1 = (calib_data[0] &
+ TSENS1_CONTR_14_POINT1_MASK)
+ >> TSENS1_CONTR_14_POINT1_SHIFT;
+ tsens2_point1 = (calib_data[0] &
+ TSENS2_CONTR_14_POINT1_MASK_0_4)
+ >> TSENS2_CONTR_14_POINT1_SHIFT_0_4;
+ temp = (calib_data[1] & TSENS2_CONTR_14_POINT1_MASK_5)
+ << TSENS2_CONTR_14_POINT1_SHIFT_5;
+ tsens2_point1 |= temp;
+ tsens3_point1 = (calib_data[1] &
+ TSENS3_CONTR_14_POINT1_MASK)
+ >> TSENS3_CONTR_14_POINT1_SHIFT;
+ tsens4_point1 = (calib_data[1] &
+ TSENS4_CONTR_14_POINT1_MASK)
+ >> TSENS4_CONTR_14_POINT1_SHIFT;
+ tsens5_point1 = (calib_data[2] &
+ TSENS5_CONTR_14_POINT1_MASK)
+ >> TSENS5_CONTR_14_POINT1_SHIFT;
+ tsens6_point1 = (calib_data[2] &
+ TSENS6_CONTR_14_POINT1_MASK)
+ >> TSENS6_CONTR_14_POINT1_SHIFT;
+ tsens7_point1 = (calib_data[3] &
+ TSENS7_CONTR_14_POINT1_MASK);
+ tsens8_point1 = (calib_data[3] &
+ TSENS8_CONTR_14_POINT1_MASK)
+ >> TSENS8_CONTR_14_POINT1_SHIFT;
+ tsens9_point1 = (calib_data[4] &
+ TSENS9_CONTR_14_POINT1_MASK);
+ tsens10_point1 = (calib_data[4] &
+ TSENS10_CONTR_14_POINT1_MASK)
+ >> TSENS10_CONTR_14_POINT1_SHIFT;
+ }
+
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ tsens_base1_data = (calib_data[3] &
+ TSENS_CONTR_14_BASE1_MASK)
+ >> TSENS_CONTR_14_BASE1_SHIFT;
+ tsens0_point2 = (calib_data[0] &
+ TSENS0_CONTR_14_POINT2_MASK)
+ >> TSENS0_CONTR_14_POINT2_SHIFT;
+ tsens1_point2 = (calib_data[0] &
+ TSENS1_CONTR_14_POINT2_MASK)
+ >> TSENS1_CONTR_14_POINT2_SHIFT;
+ tsens2_point2 = (calib_data[1] &
+ TSENS2_CONTR_14_POINT2_MASK)
+ >> TSENS2_CONTR_14_POINT2_SHIFT;
+ tsens3_point2 = (calib_data[1] &
+ TSENS3_CONTR_14_POINT2_MASK)
+ >> TSENS3_CONTR_14_POINT2_SHIFT;
+ tsens4_point2 = (calib_data[1] &
+ TSENS4_CONTR_14_POINT2_MASK)
+ >> TSENS4_CONTR_14_POINT2_SHIFT;
+ tsens5_point2 = (calib_data[2] &
+ TSENS5_CONTR_14_POINT2_MASK)
+ >> TSENS5_CONTR_14_POINT2_SHIFT;
+ tsens6_point2 = (calib_data[2] &
+ TSENS6_CONTR_14_POINT2_MASK)
+ >> TSENS6_CONTR_14_POINT2_SHIFT;
+ tsens7_point2 = (calib_data[3] &
+ TSENS7_CONTR_14_POINT2_MASK)
+ >> TSENS7_CONTR_14_POINT2_SHIFT;
+ tsens8_point2 = (calib_data[3] &
+ TSENS8_CONTR_14_POINT2_MASK)
+ >> TSENS8_CONTR_14_POINT2_SHIFT;
+ tsens9_point2 = (calib_data[4] &
+ TSENS9_CONTR_14_POINT2_MASK)
+ >> TSENS9_CONTR_14_POINT2_SHIFT;
+ tsens10_point2 = (calib_data[4] &
+ TSENS10_CONTR_14_POINT2_MASK)
+ >> TSENS10_CONTR_14_POINT2_SHIFT;
+ }
+
+ if (tsens_calibration_mode == 0) {
+ pr_debug("TSENS in calibrationless mode\n");
+ for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+ calib_tsens_point2_data[i] = TSENS_NO_CALIB_POINT2_DATA;
+ calib_tsens_point1_data[i] = TSENS_NO_CALIB_POINT1_DATA;
+ }
+ }
+
+ if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) ||
+ (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
+ calib_tsens_point1_data[0] =
+ (((tsens_base0_data) + tsens0_point1) << 2);
+ calib_tsens_point1_data[0] = calib_tsens_point1_data[0] +
+ TSENS_MSM8952_D30_WA_S0;
+ calib_tsens_point1_data[1] =
+ (((tsens_base0_data) + tsens1_point1) << 2);
+ calib_tsens_point1_data[1] = calib_tsens_point1_data[1] -
+ TSENS_MSM8952_D30_WA_S1;
+ calib_tsens_point1_data[2] =
+ (((tsens_base0_data) + tsens2_point1) << 2);
+ calib_tsens_point1_data[2] = calib_tsens_point1_data[2] +
+ TSENS_MSM8952_D30_WA_S2;
+ calib_tsens_point1_data[3] =
+ (((tsens_base0_data) + tsens3_point1) << 2);
+ calib_tsens_point1_data[3] = calib_tsens_point1_data[3] +
+ TSENS_MSM8952_D30_WA_S3;
+ calib_tsens_point1_data[4] =
+ (((tsens_base0_data) + tsens4_point1) << 2);
+ calib_tsens_point1_data[4] = calib_tsens_point1_data[4] +
+ TSENS_MSM8952_D30_WA_S4;
+ calib_tsens_point1_data[5] =
+ (((tsens_base0_data) + tsens5_point1) << 2);
+ calib_tsens_point1_data[5] = calib_tsens_point1_data[5] -
+ TSENS_MSM8952_D30_WA_S5;
+ calib_tsens_point1_data[6] =
+ (((tsens_base0_data) + tsens6_point1) << 2);
+ calib_tsens_point1_data[7] =
+ (((tsens_base0_data) + tsens7_point1) << 2);
+ calib_tsens_point1_data[7] = calib_tsens_point1_data[7] +
+ TSENS_MSM8952_D30_WA_S7;
+ calib_tsens_point1_data[8] =
+ (((tsens_base0_data) + tsens8_point1) << 2);
+ calib_tsens_point1_data[8] = calib_tsens_point1_data[8] +
+ TSENS_MSM8952_D30_WA_S8;
+ calib_tsens_point1_data[9] =
+ (((tsens_base0_data) + tsens9_point1) << 2);
+ calib_tsens_point1_data[10] =
+ (((tsens_base0_data) + tsens10_point1) << 2);
+ calib_tsens_point1_data[10] = calib_tsens_point1_data[10] -
+ TSENS_MSM8952_D30_WA_S10;
+ }
+
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ pr_debug("two point calibration calculation\n");
+ calib_tsens_point2_data[0] =
+ ((tsens_base1_data + tsens0_point2) << 2);
+ calib_tsens_point1_data[0] = calib_tsens_point1_data[0] -
+ TSENS_MSM8952_D120_WA_S0;
+ calib_tsens_point2_data[1] =
+ ((tsens_base1_data + tsens1_point2) << 2);
+ calib_tsens_point1_data[1] = calib_tsens_point1_data[1] -
+ TSENS_MSM8952_D120_WA_S1;
+ calib_tsens_point2_data[2] =
+ ((tsens_base1_data + tsens2_point2) << 2);
+ calib_tsens_point1_data[2] = calib_tsens_point1_data[2] +
+ TSENS_MSM8952_D120_WA_S2;
+ calib_tsens_point2_data[3] =
+ ((tsens_base1_data + tsens3_point2) << 2);
+ calib_tsens_point1_data[3] = calib_tsens_point1_data[3] +
+ TSENS_MSM8952_D120_WA_S3;
+ calib_tsens_point2_data[4] =
+ ((tsens_base1_data + tsens4_point2) << 2);
+ calib_tsens_point1_data[4] = calib_tsens_point1_data[4] +
+ TSENS_MSM8952_D120_WA_S4;
+ calib_tsens_point2_data[5] =
+ ((tsens_base1_data + tsens5_point2) << 2);
+ calib_tsens_point1_data[5] = calib_tsens_point1_data[5] -
+ TSENS_MSM8952_D120_WA_S5;
+ calib_tsens_point2_data[6] =
+ ((tsens_base1_data + tsens6_point2) << 2);
+ calib_tsens_point1_data[6] = calib_tsens_point1_data[6] -
+ TSENS_MSM8952_D120_WA_S6;
+ calib_tsens_point2_data[7] =
+ ((tsens_base1_data + tsens7_point2) << 2);
+ calib_tsens_point1_data[7] = calib_tsens_point1_data[7] +
+ TSENS_MSM8952_D120_WA_S7;
+ calib_tsens_point2_data[8] =
+ ((tsens_base1_data + tsens8_point2) << 2);
+ calib_tsens_point1_data[8] = calib_tsens_point1_data[8] +
+ TSENS_MSM8952_D120_WA_S8;
+ calib_tsens_point2_data[9] =
+ ((tsens_base1_data + tsens9_point2) << 2);
+ calib_tsens_point2_data[10] =
+ ((tsens_base1_data + tsens10_point2) << 2);
+ calib_tsens_point1_data[10] = calib_tsens_point1_data[10] -
+ TSENS_MSM8952_D120_WA_S10;
+ }
+
+ if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB_N_WA) ||
+ (tsens_calibration_mode ==
+ TSENS_TWO_POINT_CALIB_N_OFFSET_WA)) {
+ calib_tsens_point1_data[0] =
+ (((tsens_base0_data) + tsens0_point1) << 2);
+ calib_tsens_point1_data[1] =
+ (((tsens_base0_data) + tsens1_point1) << 2);
+ calib_tsens_point1_data[2] =
+ (((tsens_base0_data) + tsens2_point1) << 2);
+ calib_tsens_point1_data[3] =
+ (((tsens_base0_data) + tsens3_point1) << 2);
+ calib_tsens_point1_data[4] =
+ (((tsens_base0_data) + tsens4_point1) << 2);
+ calib_tsens_point1_data[5] =
+ (((tsens_base0_data) + tsens5_point1) << 2);
+ calib_tsens_point1_data[6] =
+ (((tsens_base0_data) + tsens6_point1) << 2);
+ calib_tsens_point1_data[7] =
+ (((tsens_base0_data) + tsens7_point1) << 2);
+ calib_tsens_point1_data[8] =
+ (((tsens_base0_data) + tsens8_point1) << 2);
+ calib_tsens_point1_data[9] =
+ (((tsens_base0_data) + tsens9_point1) << 2);
+ calib_tsens_point1_data[10] =
+ (((tsens_base0_data) + tsens10_point1) << 2);
+ }
+
+ if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB_N_WA) ||
+ (tsens_calibration_mode ==
+ TSENS_TWO_POINT_CALIB_N_OFFSET_WA)) {
+ pr_debug("two point calibration calculation\n");
+ calib_tsens_point2_data[0] =
+ ((tsens_base1_data + tsens0_point2) << 2);
+ calib_tsens_point2_data[1] =
+ ((tsens_base1_data + tsens1_point2) << 2);
+ calib_tsens_point2_data[2] =
+ ((tsens_base1_data + tsens2_point2) << 2);
+ calib_tsens_point2_data[3] =
+ ((tsens_base1_data + tsens3_point2) << 2);
+ calib_tsens_point2_data[4] =
+ ((tsens_base1_data + tsens4_point2) << 2);
+ calib_tsens_point2_data[5] =
+ ((tsens_base1_data + tsens5_point2) << 2);
+ calib_tsens_point2_data[6] =
+ ((tsens_base1_data + tsens6_point2) << 2);
+ calib_tsens_point2_data[7] =
+ ((tsens_base1_data + tsens7_point2) << 2);
+ calib_tsens_point2_data[8] =
+ ((tsens_base1_data + tsens8_point2) << 2);
+ calib_tsens_point2_data[9] =
+ ((tsens_base1_data + tsens9_point2) << 2);
+ calib_tsens_point2_data[10] =
+ ((tsens_base1_data + tsens10_point2) << 2);
+ }
+
+ for (i = 0; i < tmdev->tsens_num_sensor; i++) {
+ int32_t num = 0, den = 0;
+
+ tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
+ tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
+ pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
+ i, tmdev->sensor[i].calib_data_point1,
+ tmdev->sensor[i].calib_data_point2);
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
+ /*
+ * slope (m) = adc_code2 - adc_code1 (y2 - y1)
+ * temp_120_degc - temp_30_degc (x2 - x1)
+ */
+ num = tmdev->sensor[i].calib_data_point2 -
+ tmdev->sensor[i].calib_data_point1;
+ num *= tmdev->tsens_factor;
+ den = TSENS_CAL_DEGC_POINT2 - TSENS_CAL_DEGC_POINT1;
+ tmdev->sensor[i].slope_mul_tsens_factor = num/den;
+ }
+ tmdev->sensor[i].offset = (tmdev->sensor[i].calib_data_point1 *
+ tmdev->tsens_factor) - (TSENS_CAL_DEGC_POINT1 *
+ tmdev->sensor[i].slope_mul_tsens_factor);
+ pr_debug("offset:%d and slope:%d\n", tmdev->sensor[i].offset,
+ tmdev->sensor[i].slope_mul_tsens_factor);
+ tmdev->prev_reading_avail = false;
+ }
+ return 0;
}
-static int tsens_calib_msm8909_sensors(void)
+static int tsens_calib_msm8909_sensors(struct tsens_tm_device *tmdev)
{
int i, tsens_base0_data = 0, tsens_base1_data = 0;
int tsens0_point1 = 0, tsens0_point2 = 0;
@@ -1587,6 +3380,7 @@ static int tsens_calib_msm8909_sensors(void)
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
int32_t num = 0, den = 0;
+
tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
@@ -1612,7 +3406,7 @@ static int tsens_calib_msm8909_sensors(void)
return 0;
}
-static int tsens_calib_8939_sensors(void)
+static int tsens_calib_8939_sensors(struct tsens_tm_device *tmdev)
{
int i, tsens_base0_data = 0, tsens_base1_data = 0;
int tsens0_point1 = 0, tsens0_point2 = 0;
@@ -1754,6 +3548,7 @@ static int tsens_calib_8939_sensors(void)
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
int32_t num = 0, den = 0;
+
tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
@@ -1779,7 +3574,7 @@ static int tsens_calib_8939_sensors(void)
return 0;
}
-static int tsens_calib_8916_sensors(void)
+static int tsens_calib_8916_sensors(struct tsens_tm_device *tmdev)
{
int i, tsens_base0_data = 0, tsens_base1_data = 0;
int tsens0_point1 = 0, tsens0_point2 = 0;
@@ -1877,6 +3672,7 @@ static int tsens_calib_8916_sensors(void)
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
int32_t num = 0, den = 0;
+
tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
@@ -1902,7 +3698,7 @@ static int tsens_calib_8916_sensors(void)
return 0;
}
-static int tsens_calib_9630_sensors(void)
+static int tsens_calib_9630_sensors(struct tsens_tm_device *tmdev)
{
int i, tsens_base0_data = 0, tsens0_point = 0, tsens1_point = 0;
int tsens2_point = 0, tsens3_point = 0, tsens4_point = 0;
@@ -1955,6 +3751,7 @@ calibration_less_mode:
compute_intercept_slope:
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
int32_t num = 0, den = 0, adc_code_of_tempx = 0;
+
tmdev->sensor[i].calib_data_point2 = tsens_base1_data;
tmdev->sensor[i].calib_data_point1 = tsens_base0_data;
pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
@@ -1984,7 +3781,7 @@ compute_intercept_slope:
return 0;
}
-static int tsens_calib_8994_sensors(void)
+static int tsens_calib_8994_sensors(struct tsens_tm_device *tmdev)
{
int i, tsens_base0_data = 0, tsens0_point = 0, tsens1_point = 0;
int tsens2_point = 0, tsens3_point = 0, tsens4_point = 0;
@@ -2197,6 +3994,7 @@ calibration_less_mode:
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
int32_t num = 0, den = 0, adc_code_of_tempx = 0;
+
tmdev->sensor[i].calib_data_point2 = tsens_base1_data;
tmdev->sensor[i].calib_data_point1 = tsens_base0_data;
pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
@@ -2226,7 +4024,7 @@ calibration_less_mode:
return 0;
}
-static int tsens_calib_8992_sensors(void)
+static int tsens_calib_8992_sensors(struct tsens_tm_device *tmdev)
{
int i, tsens_base0_data = 0, tsens0_point = 0, tsens1_point = 0;
int tsens2_point = 0, tsens3_point = 0, tsens4_point = 0;
@@ -2424,6 +4222,7 @@ calibration_less_mode:
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
int32_t num = 0, den = 0, adc_code_of_tempx = 0;
+
tmdev->sensor[i].calib_data_point2 = tsens_base1_data;
tmdev->sensor[i].calib_data_point1 = tsens_base0_data;
pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
@@ -2453,7 +4252,7 @@ calibration_less_mode:
return 0;
}
-static int tsens_calib_8x10_sensors(void)
+static int tsens_calib_8x10_sensors(struct tsens_tm_device *tmdev)
{
int i, tsens_base0_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
int tsens0_point2 = 0, tsens1_point2 = 0;
@@ -2538,6 +4337,7 @@ calibration_less_mode:
compute_intercept_slope:
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
int32_t num = 0, den = 0;
+
tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
@@ -2561,7 +4361,7 @@ compute_intercept_slope:
return 0;
}
-static int tsens_calib_8x26_sensors(void)
+static int tsens_calib_8x26_sensors(struct tsens_tm_device *tmdev)
{
int i, tsens_base0_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
int tsens2_point1 = 0, tsens3_point1 = 0, tsens4_point1 = 0;
@@ -2694,6 +4494,7 @@ calibration_less_mode:
compute_intercept_slope:
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
int32_t num = 0, den = 0;
+
tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
@@ -2717,7 +4518,7 @@ compute_intercept_slope:
return 0;
}
-static int tsens_calib_8974_sensors(void)
+static int tsens_calib_8974_sensors(struct tsens_tm_device *tmdev)
{
int i, tsens_base1_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
int tsens2_point1 = 0, tsens3_point1 = 0, tsens4_point1 = 0;
@@ -3027,6 +4828,7 @@ calibration_less_mode:
compute_intercept_slope:
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
int32_t num = 0, den = 0;
+
tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
@@ -3051,7 +4853,7 @@ compute_intercept_slope:
return 0;
}
-static int tsens_calib_9900_sensors(void)
+static int tsens_calib_9900_sensors(struct tsens_tm_device *tmdev)
{
int i, tsens_base1_data = 0, tsens0_point1 = 0, tsens1_point1 = 0;
int tsens2_point1 = 0, tsens3_point1 = 0, tsens4_point1 = 0;
@@ -3299,6 +5101,7 @@ calibration_less_mode:
compute_intercept_slope:
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
int32_t num = 0, den = 0;
+
tmdev->sensor[i].calib_data_point2 = calib_tsens_point2_data[i];
tmdev->sensor[i].calib_data_point1 = calib_tsens_point1_data[i];
pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
@@ -3323,7 +5126,7 @@ compute_intercept_slope:
return 0;
}
-static int tsens_calib_msmzirc_sensors(void)
+static int tsens_calib_msmzirc_sensors(struct tsens_tm_device *tmdev)
{
int i = 0, tsens_base0_data = 0, tsens_base1_data = 0;
int tsens0_point = 0, tsens1_point = 0, tsens2_point = 0;
@@ -3344,7 +5147,7 @@ static int tsens_calib_msmzirc_sensors(void)
pr_debug("calib mode is %d\n", tsens_calibration_mode);
}
- if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) {
+ if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) {
tsens_base0_data = (calib_data[0] & TSENS_BASE0_ZIRC_MASK);
tsens_base1_data = (calib_data[0] & TSENS_BASE1_ZIRC_MASK) >>
TSENS_BASE1_ZIRC_SHIFT;
@@ -3375,6 +5178,7 @@ static int tsens_calib_msmzirc_sensors(void)
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
int32_t num = 0, den = 0, adc_code_of_tempx = 0;
+
tmdev->sensor[i].calib_data_point2 = tsens_base1_data;
tmdev->sensor[i].calib_data_point1 = tsens_base0_data;
pr_debug("sensor:%d - calib_data_point1:0x%x, calib_data_point2:0x%x\n",
@@ -3403,35 +5207,45 @@ static int tsens_calib_msmzirc_sensors(void)
return 0;
}
-static int tsens_calib_sensors(void)
+static int tsens_calib_sensors(struct tsens_tm_device *tmdev)
{
int rc = 0;
+ pr_debug("%s\n", __func__);
+
if (!tmdev)
return -ENODEV;
if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8974)
- rc = tsens_calib_8974_sensors();
+ rc = tsens_calib_8974_sensors(tmdev);
else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8X26)
- rc = tsens_calib_8x26_sensors();
+ rc = tsens_calib_8x26_sensors(tmdev);
else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8X10)
- rc = tsens_calib_8x10_sensors();
+ rc = tsens_calib_8x10_sensors(tmdev);
else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_9900)
- rc = tsens_calib_9900_sensors();
+ rc = tsens_calib_9900_sensors(tmdev);
else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_9630)
- rc = tsens_calib_9630_sensors();
+ rc = tsens_calib_9630_sensors(tmdev);
else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8916)
- rc = tsens_calib_8916_sensors();
+ rc = tsens_calib_8916_sensors(tmdev);
else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8939)
- rc = tsens_calib_8939_sensors();
+ rc = tsens_calib_8939_sensors(tmdev);
else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8994)
- rc = tsens_calib_8994_sensors();
+ rc = tsens_calib_8994_sensors(tmdev);
else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_MSM8909)
- rc = tsens_calib_msm8909_sensors();
+ rc = tsens_calib_msm8909_sensors(tmdev);
else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_MSMZIRC)
- rc = tsens_calib_msmzirc_sensors();
+ rc = tsens_calib_msmzirc_sensors(tmdev);
else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8992)
- rc = tsens_calib_8992_sensors();
+ rc = tsens_calib_8992_sensors(tmdev);
+ else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_MSM8952)
+ rc = tsens_calib_msm8952_sensors(tmdev);
+ else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_MDM9607)
+ rc = tsens_calib_mdm9607_sensors(tmdev);
+ else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_MSM8937)
+ rc = tsens_calib_msm8937_msmgold_sensors(tmdev);
+ else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_MSMGOLD)
+ rc = tsens_calib_msm8937_msmgold_sensors(tmdev);
else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_NONE) {
pr_debug("Fuse map info not required\n");
rc = 0;
@@ -3443,52 +5257,14 @@ static int tsens_calib_sensors(void)
return rc;
}
-static struct of_device_id tsens_match[] = {
- { .compatible = "qcom,msm-tsens",
- .data = (void *)TSENS_CALIB_FUSE_MAP_8974,
- },
- { .compatible = "qcom,msm8x26-tsens",
- .data = (void *)TSENS_CALIB_FUSE_MAP_8X26,
- },
- { .compatible = "qcom,msm8x10-tsens",
- .data = (void *)TSENS_CALIB_FUSE_MAP_8X10,
- },
- { .compatible = "qcom,fsm9900-tsens",
- .data = (void *)TSENS_CALIB_FUSE_MAP_9900,
- },
- { .compatible = "qcom,mdm9630-tsens",
- .data = (void *)TSENS_CALIB_FUSE_MAP_9630,
- },
- { .compatible = "qcom,msm8916-tsens",
- .data = (void *)TSENS_CALIB_FUSE_MAP_8916,
- },
- { .compatible = "qcom,msm8939-tsens",
- .data = (void *)TSENS_CALIB_FUSE_MAP_8939,
- },
- { .compatible = "qcom,msm8994-tsens",
- .data = (void *)TSENS_CALIB_FUSE_MAP_8994,
- },
- { .compatible = "qcom,msm8909-tsens",
- .data = (void *)TSENS_CALIB_FUSE_MAP_MSM8909,
- },
- { .compatible = "qcom,msmzirc-tsens",
- .data = (void *)TSENS_CALIB_FUSE_MAP_MSMZIRC,
- },
- { .compatible = "qcom,msm8996-tsens",
- .data = (void *)TSENS_CALIB_FUSE_MAP_NONE,
- },
- { .compatible = "qcom,msm8992-tsens",
- .data = (void *)TSENS_CALIB_FUSE_MAP_8992,
- },
- {}
-};
-
-static int get_device_tree_data(struct platform_device *pdev)
+static int get_device_tree_data(struct platform_device *pdev,
+ struct tsens_tm_device *tmdev)
{
struct device_node *of_node = pdev->dev.of_node;
struct resource *res_mem = NULL;
- u32 *tsens_slope_data, *sensor_id;
- u32 rc = 0, i, tsens_num_sensors;
+ u32 *tsens_slope_data, *sensor_id, *client_id;
+ u32 *temp1_calib_offset_factor, *temp2_calib_offset_factor;
+ u32 rc = 0, i, tsens_num_sensors = 0;
const struct of_device_id *id;
rc = of_property_read_u32(of_node,
@@ -3498,12 +5274,15 @@ static int get_device_tree_data(struct platform_device *pdev)
return -ENODEV;
}
+ if (tsens_num_sensors == 0) {
+ pr_err("No sensors?\n");
+ return -ENODEV;
+ }
+
tsens_slope_data = devm_kzalloc(&pdev->dev,
tsens_num_sensors * sizeof(u32), GFP_KERNEL);
- if (!tsens_slope_data) {
- dev_err(&pdev->dev, "can not allocate slope data\n");
+ if (!tsens_slope_data)
return -ENOMEM;
- }
rc = of_property_read_u32_array(of_node,
"qcom,slope", tsens_slope_data, tsens_num_sensors);
@@ -3515,22 +5294,12 @@ static int get_device_tree_data(struct platform_device *pdev)
if (!of_match_node(tsens_match, of_node)) {
pr_err("Need to read SoC specific fuse map\n");
return -ENODEV;
- } else {
- id = of_match_node(tsens_match, of_node);
- if (id == NULL) {
- pr_err("can not find tsens_match of_node\n");
- return -ENODEV;
- }
}
- tmdev = devm_kzalloc(&pdev->dev,
- sizeof(struct tsens_tm_device) +
- tsens_num_sensors *
- sizeof(struct tsens_tm_device_sensor),
- GFP_KERNEL);
- if (tmdev == NULL) {
- pr_err("%s: kzalloc() failed.\n", __func__);
- return -ENOMEM;
+ id = of_match_node(tsens_match, of_node);
+ if (id == NULL) {
+ pr_err("can not find tsens_match of_node\n");
+ return -ENODEV;
}
for (i = 0; i < tsens_num_sensors; i++)
@@ -3545,9 +5314,24 @@ static int get_device_tree_data(struct platform_device *pdev)
sensor_id = devm_kzalloc(&pdev->dev,
tsens_num_sensors * sizeof(u32), GFP_KERNEL);
- if (!sensor_id) {
- dev_err(&pdev->dev, "can not allocate sensor id\n");
+ if (!sensor_id)
+ return -ENOMEM;
+
+ client_id = devm_kzalloc(&pdev->dev,
+ tsens_num_sensors * sizeof(u32), GFP_KERNEL);
+ if (!client_id)
return -ENOMEM;
+
+ rc = of_property_read_u32_array(of_node,
+ "qcom,client-id", client_id, tsens_num_sensors);
+ if (rc) {
+ for (i = 0; i < tsens_num_sensors; i++)
+ tmdev->sensor[i].sensor_client_id = i;
+ pr_debug("Default client id mapping\n");
+ } else {
+ for (i = 0; i < tsens_num_sensors; i++)
+ tmdev->sensor[i].sensor_client_id = client_id[i];
+ pr_debug("Use specified client id mapping\n");
}
rc = of_property_read_u32_array(of_node,
@@ -3573,16 +5357,28 @@ static int get_device_tree_data(struct platform_device *pdev)
tmdev->tsens_type = TSENS_TYPE2;
else if (!strcmp(id->compatible, "qcom,msm8996-tsens"))
tmdev->tsens_type = TSENS_TYPE3;
+ else if (!strcmp(id->compatible, "qcom,msmtitanium-tsens")) {
+ tmdev->tsens_type = TSENS_TYPE3;
+ tsens_poll_check = 0;
+ } else if (!strcmp(id->compatible, "qcom,msm8952-tsens") ||
+ (!strcmp(id->compatible, "qcom,msmgold-tsens")) ||
+ (!strcmp(id->compatible, "qcom,msm8937-tsens")))
+ tmdev->tsens_type = TSENS_TYPE4;
else
tmdev->tsens_type = TSENS_TYPE0;
- if (!strcmp(id->compatible, "qcom,msm8994-tsens") ||
+ tmdev->tsens_valid_status_check = of_property_read_bool(of_node,
+ "qcom,valid-status-check");
+ if (!tmdev->tsens_valid_status_check) {
+ if (!strcmp(id->compatible, "qcom,msm8994-tsens") ||
(!strcmp(id->compatible, "qcom,msmzirc-tsens")) ||
(!strcmp(id->compatible, "qcom,msm8992-tsens")) ||
- (!strcmp(id->compatible, "qcom,msm8996-tsens")))
- tmdev->tsens_valid_status_check = true;
- else
- tmdev->tsens_valid_status_check = false;
+ (!strcmp(id->compatible, "qcom,msm8996-tsens")) ||
+ (!strcmp(id->compatible, "qcom,msm8952-tsens")) ||
+ (!strcmp(id->compatible, "qcom,msm8937-tsens")) ||
+ (!strcmp(id->compatible, "qcom,msmtitanium-tsens")))
+ tmdev->tsens_valid_status_check = true;
+ }
tmdev->tsens_irq = platform_get_irq_byname(pdev,
"tsens-upper-lower");
@@ -3592,7 +5388,8 @@ static int get_device_tree_data(struct platform_device *pdev)
goto fail_tmdev;
}
- if (!strcmp(id->compatible, "qcom,msm8996-tsens")) {
+ if (!strcmp(id->compatible, "qcom,msm8996-tsens") ||
+ (!strcmp(id->compatible, "qcom,msmtitanium-tsens"))) {
tmdev->tsens_critical_irq =
platform_get_irq_byname(pdev,
"tsens-critical");
@@ -3603,6 +5400,44 @@ static int get_device_tree_data(struct platform_device *pdev)
}
}
+ temp1_calib_offset_factor = devm_kzalloc(&pdev->dev,
+ tsens_num_sensors * sizeof(u32), GFP_KERNEL);
+ if (!temp1_calib_offset_factor)
+ return -ENOMEM;
+
+ rc = of_property_read_u32_array(of_node,
+ "qcom,temp1-offset", temp1_calib_offset_factor,
+ tsens_num_sensors);
+ if (rc) {
+ pr_debug("Default temp1-offsets\n");
+ for (i = 0; i < tsens_num_sensors; i++)
+ tmdev->sensor[i].wa_temp1_calib_offset_factor = 0;
+ } else {
+ pr_debug("Use specific temp1-offsets\n");
+ for (i = 0; i < tsens_num_sensors; i++)
+ tmdev->sensor[i].wa_temp1_calib_offset_factor =
+ temp1_calib_offset_factor[i];
+ }
+
+ temp2_calib_offset_factor = devm_kzalloc(&pdev->dev,
+ tsens_num_sensors * sizeof(u32), GFP_KERNEL);
+ if (!temp2_calib_offset_factor)
+ return -ENOMEM;
+
+ rc = of_property_read_u32_array(of_node,
+ "qcom,temp2-offset", temp2_calib_offset_factor,
+ tsens_num_sensors);
+ if (rc) {
+ pr_debug("Default temp2-offsets\n");
+ for (i = 0; i < tsens_num_sensors; i++)
+ tmdev->sensor[i].wa_temp2_calib_offset_factor = 0;
+ } else {
+ pr_debug("Use specific temp2-offsets\n");
+ for (i = 0; i < tsens_num_sensors; i++)
+ tmdev->sensor[i].wa_temp2_calib_offset_factor =
+ temp2_calib_offset_factor[i];
+ }
+
/* TSENS register region */
tmdev->res_tsens_mem = platform_get_resource_byname(pdev,
IORESOURCE_MEM, "tsens_physical");
@@ -3642,28 +5477,16 @@ static int get_device_tree_data(struct platform_device *pdev)
tmdev->calib_len = tmdev->res_calib_mem->end -
tmdev->res_calib_mem->start + 1;
- res_mem = request_mem_region(tmdev->res_calib_mem->start,
- tmdev->calib_len, tmdev->res_calib_mem->name);
- if (!res_mem) {
- pr_err("Request calibration memory region failed\n");
- rc = -EINVAL;
- goto fail_unmap_tsens;
- }
-
- tmdev->tsens_calib_addr = ioremap(res_mem->start,
+ tmdev->tsens_calib_addr = ioremap(tmdev->res_calib_mem->start,
tmdev->calib_len);
if (!tmdev->tsens_calib_addr) {
pr_err("Failed to IO map EEPROM registers.\n");
rc = -EINVAL;
- goto fail_unmap_calib_region;
+ goto fail_unmap_tsens;
}
return 0;
-fail_unmap_calib_region:
- if (tmdev->res_calib_mem)
- release_mem_region(tmdev->res_calib_mem->start,
- tmdev->calib_len);
fail_unmap_tsens:
if (tmdev->tsens_addr)
iounmap(tmdev->tsens_addr);
@@ -3672,21 +5495,32 @@ fail_unmap_tsens_region:
release_mem_region(tmdev->res_tsens_mem->start,
tmdev->tsens_len);
fail_tmdev:
- tmdev = NULL;
+ platform_set_drvdata(pdev, NULL);
+
return rc;
}
static int tsens_tm_probe(struct platform_device *pdev)
{
+ struct device_node *of_node = pdev->dev.of_node;
int rc, i;
+ u32 tsens_num_sensors;
+ struct tsens_tm_device *tmdev = NULL;
- if (tmdev) {
- pr_err("TSENS device already in use\n");
- return -EBUSY;
+ rc = of_property_read_u32(of_node,
+ "qcom,sensors", &tsens_num_sensors);
+ tmdev = devm_kzalloc(&pdev->dev,
+ sizeof(struct tsens_tm_device) +
+ tsens_num_sensors *
+ sizeof(struct tsens_tm_device_sensor),
+ GFP_KERNEL);
+ if (tmdev == NULL) {
+ pr_err("%s: kzalloc() failed.\n", __func__);
+ return -ENOMEM;
}
if (pdev->dev.of_node) {
- rc = get_device_tree_data(pdev);
+ rc = get_device_tree_data(pdev, tmdev);
if (rc) {
pr_err("Error reading TSENS DT\n");
return rc;
@@ -3703,88 +5537,134 @@ static int tsens_tm_probe(struct platform_device *pdev)
goto fail;
}
- rc = tsens_calib_sensors();
+ rc = tsens_calib_sensors(tmdev);
if (rc < 0) {
pr_err("Calibration failed\n");
goto fail;
}
- tsens_hw_init();
+ rc = tsens_hw_init(tmdev);
+ if (rc)
+ return rc;
tmdev->prev_reading_avail = true;
for (i = 0; i < 16; i++)
tmdev->sensor_dbg_info[i].idx = 0;
+ spin_lock_init(&tmdev->tsens_crit_lock);
+ spin_lock_init(&tmdev->tsens_upp_low_lock);
tmdev->is_ready = true;
+ list_add_tail(&tmdev->list, &tsens_device_list);
platform_set_drvdata(pdev, tmdev);
+ rc = create_tsens_mtc_sysfs(pdev);
+ if (rc < 0)
+ pr_debug("Cannot create create_tsens_mtc_sysfs %d\n", rc);
+
return 0;
fail:
if (tmdev->tsens_critical_wq)
destroy_workqueue(tmdev->tsens_critical_wq);
if (tmdev->tsens_calib_addr)
iounmap(tmdev->tsens_calib_addr);
- if (tmdev->res_calib_mem)
- release_mem_region(tmdev->res_calib_mem->start,
- tmdev->calib_len);
if (tmdev->tsens_addr)
iounmap(tmdev->tsens_addr);
if (tmdev->res_tsens_mem)
release_mem_region(tmdev->res_tsens_mem->start,
tmdev->tsens_len);
- tmdev = NULL;
+ platform_set_drvdata(pdev, NULL);
return rc;
}
-static int _tsens_register_thermal(void)
+static ssize_t tsens_debugfs_read(struct file *file, char __user *ubuf,
+ size_t count, loff_t *ppos)
{
- struct platform_device *pdev;
- int rc, i;
+ int nbytes = 0;
+ struct tsens_tm_device *tmdev = NULL;
+
+ list_for_each_entry(tmdev, &tsens_device_list, list) {
+ nbytes += scnprintf(dbg_buff + nbytes, 1024 - nbytes,
+ "TSENS Critical count: %d\n",
+ tmdev->tsens_critical_irq_cnt);
+ nbytes += scnprintf(dbg_buff + nbytes, 1024 - nbytes,
+ "TSENS Upper count: %d\n",
+ tmdev->tsens_upper_irq_cnt);
+ nbytes += scnprintf(dbg_buff + nbytes, 1024 - nbytes,
+ "TSENS Lower count: %d\n",
+ tmdev->tsens_lower_irq_cnt);
- if (tsens_is_ready() <= 0) {
- pr_err("%s: TSENS early init not done\n", __func__);
- return -ENODEV;
}
- pdev = tmdev->pdev;
+ return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, nbytes);
+}
+
+const struct file_operations tsens_stats_ops = {
+ .read = tsens_debugfs_read,
+};
+
+static void tsens_debugfs_init(void)
+{
+ const mode_t read_only_mode = S_IRUSR | S_IRGRP | S_IROTH;
+
+ dent = debugfs_create_dir("tsens", 0);
+ if (IS_ERR(dent)) {
+ pr_err("Error creating TSENS directory\n");
+ return;
+ }
+
+ dfile_stats = debugfs_create_file("stats", read_only_mode, dent,
+ 0, &tsens_stats_ops);
+ if (!dfile_stats || IS_ERR(dfile_stats)) {
+ pr_err("Failed to create TSENS folder\n");
+ return;
+ }
+}
+
+int tsens_sensor_sw_idx = 0;
+
+static int tsens_thermal_zone_register(struct tsens_tm_device *tmdev)
+{
+ int rc = 0, i = 0;
+
+ if (tmdev == NULL) {
+ pr_err("Invalid tsens instance\n");
+ return -EINVAL;
+ }
for (i = 0; i < tmdev->tsens_num_sensor; i++) {
char name[18];
+
snprintf(name, sizeof(name), "tsens_tz_sensor%d",
- tmdev->sensor[i].sensor_hw_num);
+ tsens_sensor_sw_idx);
tmdev->sensor[i].mode = THERMAL_DEVICE_ENABLED;
+ tmdev->sensor[i].tm = tmdev;
if (tmdev->tsens_type == TSENS_TYPE3) {
- tmdev->sensor[i].tz_dev =
- thermal_zone_device_register(name,
- TSENS_TM_TRIP_NUM,
+ tmdev->sensor[i].tz_dev = thermal_zone_device_register(
+ name, TSENS_TM_TRIP_NUM,
TSENS_TM_WRITABLE_TRIPS_MASK,
&tmdev->sensor[i],
- &tsens_tm_thermal_zone_ops,
- NULL, 0, 0);
+ &tsens_tm_thermal_zone_ops, NULL, 0, 0);
if (IS_ERR(tmdev->sensor[i].tz_dev)) {
- pr_err("%s: thermal_zone_device_register() failed.\n",
- __func__);
+ pr_err("%s: failed.\n", __func__);
rc = -ENODEV;
goto fail;
}
} else {
- tmdev->sensor[i].tz_dev =
- thermal_zone_device_register(name,
- TSENS_TRIP_NUM,
- TSENS_WRITABLE_TRIPS_MASK,
- &tmdev->sensor[i],
- &tsens_thermal_zone_ops,
- NULL, 0, 0);
+ tmdev->sensor[i].tz_dev = thermal_zone_device_register(
+ name, TSENS_TRIP_NUM,
+ TSENS_WRITABLE_TRIPS_MASK,
+ &tmdev->sensor[i],
+ &tsens_thermal_zone_ops, NULL, 0, 0);
if (IS_ERR(tmdev->sensor[i].tz_dev)) {
- pr_err("%s: thermal_zone_device_register() failed.\n",
- __func__);
+ pr_err("%s: failed.\n", __func__);
rc = -ENODEV;
goto fail;
}
}
+ tsens_sensor_sw_idx++;
}
if (tmdev->tsens_type == TSENS_TYPE3) {
@@ -3803,24 +5683,30 @@ static int _tsens_register_thermal(void)
}
rc = request_threaded_irq(tmdev->tsens_critical_irq, NULL,
- tsens_tm_critical_irq_thread,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
- "tsens_critical_interrupt", tmdev);
+ tsens_tm_critical_irq_thread,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "tsens_critical_interrupt", tmdev);
if (rc < 0) {
pr_err("%s: request_irq FAIL: %d\n", __func__, rc);
for (i = 0; i < tmdev->tsens_num_sensor; i++)
thermal_zone_device_unregister(
- tmdev->sensor[i].tz_dev);
+ tmdev->sensor[i].tz_dev);
goto fail;
} else {
enable_irq_wake(tmdev->tsens_critical_irq);
}
+
+ if (tsens_poll_check) {
+ INIT_DEFERRABLE_WORK(&tmdev->tsens_critical_poll_test,
+ tsens_poll);
+ schedule_delayed_work(&tmdev->tsens_critical_poll_test,
+ msecs_to_jiffies(tsens_sec_to_msec_value));
+ init_completion(&tmdev->tsens_rslt_completion);
+ }
} else {
rc = request_threaded_irq(tmdev->tsens_irq, NULL,
- tsens_irq_thread,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
- "tsens_interrupt",
- tmdev);
+ tsens_irq_thread, IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "tsens_interrupt", tmdev);
if (rc < 0) {
pr_err("%s: request_irq FAIL: %d\n", __func__, rc);
for (i = 0; i < tmdev->tsens_num_sensor; i++)
@@ -3832,15 +5718,10 @@ static int _tsens_register_thermal(void)
}
}
- platform_set_drvdata(pdev, tmdev);
-
return 0;
fail:
if (tmdev->tsens_calib_addr)
iounmap(tmdev->tsens_calib_addr);
- if (tmdev->res_calib_mem)
- release_mem_region(tmdev->res_calib_mem->start,
- tmdev->calib_len);
if (tmdev->tsens_addr)
iounmap(tmdev->tsens_addr);
if (tmdev->res_tsens_mem)
@@ -3849,6 +5730,29 @@ fail:
return rc;
}
+static int _tsens_register_thermal(void)
+{
+ struct tsens_tm_device *tmdev = NULL;
+ int rc;
+
+ if (tsens_is_ready() <= 0) {
+ pr_err("%s: TSENS early init not done\n", __func__);
+ return -ENODEV;
+ }
+
+ list_for_each_entry(tmdev, &tsens_device_list, list) {
+ rc = tsens_thermal_zone_register(tmdev);
+ if (rc) {
+ pr_err("Error registering the thermal zone\n");
+ return rc;
+ }
+ }
+
+ tsens_debugfs_init();
+
+ return 0;
+}
+
static int tsens_tm_remove(struct platform_device *pdev)
{
struct tsens_tm_device *tmdev = platform_get_drvdata(pdev);
@@ -3858,9 +5762,6 @@ static int tsens_tm_remove(struct platform_device *pdev)
thermal_zone_device_unregister(tmdev->sensor[i].tz_dev);
if (tmdev->tsens_calib_addr)
iounmap(tmdev->tsens_calib_addr);
- if (tmdev->res_calib_mem)
- release_mem_region(tmdev->res_calib_mem->start,
- tmdev->calib_len);
if (tmdev->tsens_addr)
iounmap(tmdev->tsens_addr);
if (tmdev->res_tsens_mem)
diff --git a/include/linux/msm_tsens.h b/include/linux/msm_tsens.h
index 3dfe78b2c29b..62e59dbe8385 100644
--- a/include/linux/msm_tsens.h
+++ b/include/linux/msm_tsens.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2011-2015, 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
@@ -18,52 +18,122 @@
#ifndef __MSM_TSENS_H
#define __MSM_TSENS_H
-enum platform_type {
- MSM_8660 = 0,
- MSM_8960,
- MDM_9615,
- APQ_8064,
- MSM_TYPE
-};
-
#define TSENS_MAX_SENSORS 11
-
-struct tsens_platform_data {
- int slope[TSENS_MAX_SENSORS];
- int tsens_factor;
- uint32_t tsens_num_sensor;
- enum platform_type hw_type;
-};
+#define TSENS_MTC_ZONE_LOG_SIZE 6
+#define TSENS_NUM_MTC_ZONES_SUPPORT 3
+#define TSENS_ZONEMASK_PARAMS 3
+#define TSENS_ZONELOG_PARAMS 1
+#define TSENS_MTC_ZONE_HISTORY_SIZE 3
struct tsens_device {
uint32_t sensor_num;
};
-int32_t tsens_get_temp(struct tsens_device *dev, unsigned long *temp);
-int msm_tsens_early_init(struct tsens_platform_data *pdata);
-
#if defined(CONFIG_THERMAL_TSENS8974)
+/**
+ * tsens_is_ready() - Clients can use this API to check if the TSENS device
+ * is ready and clients can start requesting temperature reads.
+ * @return: Returns true if device is ready else returns -EPROBE_DEFER
+ * for clients to check back after a time duration.
+ */
int tsens_is_ready(void);
+/**
+ * tsens_tm_init_driver() - Early initialization for clients to read
+ * TSENS temperature.
+ */
int __init tsens_tm_init_driver(void);
-int tsens_get_sw_id_mapping(int sensor_num, int *sensor_sw_idx);
+/**
+ * tsens_get_hw_id_mapping() - Mapping software or sensor ID with the physical
+ * TSENS sensor. On certain cases where there are more number of
+ * controllers the sensor ID is used to map the clients software ID
+ * with the physical HW sensors used by the driver.
+ * @sensors_sw_id: Client ID.
+ * @sensor_hw_num: Sensor client ID passed by the driver. This ID is used
+ * by the driver to map it to the physical HW sensor
+ * number.
+ * @return: If the device is not present returns -EPROBE_DEFER
+ * for clients to check back after a time duration.
+ * 0 on success else error code on error.
+ */
int tsens_get_hw_id_mapping(int sensor_sw_id, int *sensor_hw_num);
+/**
+ * tsens_get_max_sensor_num() - Get the total number of active TSENS sensors.
+ * The total number received by the client is across multiple
+ * TSENS controllers if present.
+ * @tsens_num_sensors: Total number of sensor result to be stored.
+ */
+int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors);
+/**
+ * tsens_set_mtc_zone_sw_mask() - Mask the MTC threshold level of a zone.
+ * SW can force the MTC to stop issuing throttling commands that
+ * correspond to each MTC threshold level by writing the
+ * corresponding bit in register at any time.
+ * @zone: Zone ID.
+ * @th1_enable : Value corresponding to the threshold level.
+ * @th2_enable : Value corresponding to the threshold level.
+ */
+int tsens_set_mtc_zone_sw_mask(unsigned int zone , unsigned int th1_enable,
+ unsigned int th2_enable);
+/**
+ * tsens_get_mtc_zone_log() - Get the log of last 6 commands sent to pulse
+ * swallower of a zone.
+ * zone: Zone ID
+ * @zone_log: Log commands result to be stored.
+ */
+int tsens_get_mtc_zone_log(unsigned int zone , void *zone_log);
+/**
+ * tsens_mtc_reset_history_counter() - Reset history of throttling commands
+ * sent to pulse swallower. Tsens controller issues clock
+ * throttling commands to Pulse swallower to perform HW
+ * based clock throttling. Reset the history counter of a zone.
+ * @zone: Zone ID.
+ */
+int tsens_mtc_reset_history_counter(unsigned int zone);
+/**
+ * tsens_get_mtc_zone_history() - Get the history of throttling commands sent
+ * to pulse swallower. Tsens controller issues clock throttling
+ * commands to Pulse swallower to perform HW based clock
+ * throttling.
+ * @zone: Zone ID
+ * @zone_hist: Commands history result to be stored.
+ */
+int tsens_get_mtc_zone_history(unsigned int zone , void *zone_hist);
+/**
+ * tsens_get_temp() - Obtain the TSENS temperature for the respective sensor.
+ *
+ * @dev: Sensor number for which client wants the TSENS temperature
+ * reading. The ID passed by the sensor could be the sensor ID
+ * which the driver translates to internally to read the
+ * respective physical HW sensor from the controller.
+ * @temp: temperature result to be stored.
+ * @return: If the device is not present returns -EPROBE_DEFER
+ * for clients to check back after a time duration.
+ * 0 on success else error code on error.
+ */
+int tsens_get_temp(struct tsens_device *dev, int *temp);
#else
static inline int tsens_is_ready(void)
{ return -ENXIO; }
static inline int __init tsens_tm_init_driver(void)
{ return -ENXIO; }
-static inline int tsens_get_sw_id_mapping(
- int sensor_num, int *sensor_sw_idx)
-{ return -ENXIO; }
static inline int tsens_get_hw_id_mapping(
int sensor_sw_id, int *sensor_hw_num)
{ return -ENXIO; }
-#endif
-
-#if defined(CONFIG_THERMAL_TSENS8974)
-int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors);
-#else
static inline int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors)
{ return -ENXIO; }
+static inline int tsens_set_mtc_zone_sw_mask(unsigned int zone ,
+ unsigned int th1_enable ,
+ unsigned int th2_enable)
+{ return -ENXIO; }
+static inline int tsens_get_mtc_zone_log(unsigned int zone , void *zone_log)
+{ return -ENXIO; }
+static inline int tsens_mtc_reset_history_counter(unsigned int zone)
+{ return -ENXIO; }
+static inline int tsens_get_temp(struct tsens_device *dev,
+ int *temp)
+{ return -ENXIO; }
+static inline int tsens_get_mtc_zone_history(unsigned int zone, void *zone_hist)
+{ return -ENXIO; }
#endif
+
#endif /*MSM_TSENS_H */