/* Copyright (c) 2012-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 * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * */ #define pr_fmt(fmt) "%s: " fmt, __func__ #include #include #include #include #include #include #include #include #include #include #include #include #define CREATE_TRACE_POINTS #include #define TSENS_DRIVER_NAME "msm-tsens" /* TSENS register info */ #define TSENS_UPPER_LOWER_INTERRUPT_CTRL(n) ((n) + 0x1000) #define TSENS_INTERRUPT_EN BIT(0) #define TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(n) ((n) + 0x1004) #define TSENS_UPPER_STATUS_CLR BIT(21) #define TSENS_LOWER_STATUS_CLR BIT(20) #define TSENS_UPPER_THRESHOLD_MASK 0xffc00 #define TSENS_LOWER_THRESHOLD_MASK 0x3ff #define TSENS_UPPER_THRESHOLD_SHIFT 10 #define TSENS_S0_STATUS_ADDR(n) ((n) + 0x1030) #define TSENS_SN_ADDR_OFFSET 0x4 #define TSENS_SN_STATUS_TEMP_MASK 0x3ff #define TSENS_SN_STATUS_LOWER_STATUS BIT(11) #define TSENS_SN_STATUS_UPPER_STATUS BIT(12) #define TSENS_STATUS_ADDR_OFFSET 2 #define TSENS_TRDY_ADDR(n) ((n) + 0x105c) #define TSENS_TRDY_MASK BIT(0) #define TSENS2_SN_STATUS_ADDR(n) ((n) + 0x1044) #define TSENS2_SN_STATUS_VALID BIT(14) #define TSENS2_SN_STATUS_VALID_MASK 0x4000 #define TSENS2_TRDY_ADDR(n) ((n) + 0x1084) #define TSENS3_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 #define TSENS_CTRL_ADDR(n) (n) #define TSENS_EN BIT(0) #define TSENS_SW_RST BIT(1) #define TSENS_ADC_CLK_SEL BIT(2) #define TSENS_SENSOR0_SHIFT 3 #define TSENS_62_5_MS_MEAS_PERIOD 1 #define TSENS_312_5_MS_MEAS_PERIOD 2 #define TSENS_MEAS_PERIOD_SHIFT 18 #define TSENS_GLOBAL_CONFIG(n) ((n) + 0x34) #define TSENS_S0_MAIN_CONFIG(n) ((n) + 0x38) #define TSENS_SN_REMOTE_CONFIG(n) ((n) + 0x3c) #define TSENS_EEPROM(n) ((n) + 0xd0) #define TSENS_EEPROM_9640V2(n) ((n) + 0x8) #define TSENS_EEPROM_REDUNDANCY_SEL(n) ((n) + 0x444) #define TSENS_EEPROM_BACKUP_REGION(n) ((n) + 0x440) #define TSENS_MAIN_CALIB_ADDR_RANGE 6 #define TSENS_BACKUP_CALIB_ADDR_RANGE 4 #define TSENS_EEPROM_8X26_1(n) ((n) + 0x1c0) #define TSENS_EEPROM_8X26_2(n) ((n) + 0x444) #define TSENS_8X26_MAIN_CALIB_ADDR_RANGE 4 #define TSENS_EEPROM_8X10_1(n) ((n) + 0x1a4) #define TSENS_EEPROM_8X10_1_OFFSET 8 #define TSENS_EEPROM_8X10_2(n) ((n) + 0x1a8) #define TSENS_EEPROM_8X10_SPARE_1(n) ((n) + 0xd8) #define TSENS_EEPROM_8X10_SPARE_2(n) ((n) + 0xdc) #define TSENS_9900_EEPROM(n) ((n) + 0xd0) #define TSENS_9900_EEPROM_REDUNDANCY_SEL(n) ((n) + 0x1c4) #define TSENS_9900_EEPROM_BACKUP_REGION(n) ((n) + 0x450) #define TSENS_9900_CALIB_ADDR_RANGE 4 #define TSENS_9010_EEPROM(n) ((n) + 0xd0) #define TSENS_9010_EEPROM_REDUNDANCY_SEL(n) ((n) + 0xd4) #define TSENS_9010_EEPROM_BACKUP_REGION(n) ((n) + 0x450) #define TSENS_9010_CALIB_ADDR_RANGE 4 #define TSENS_8939_EEPROM(n) ((n) + 0xa0) #define TSENS_8994_EEPROM(n) ((n) + 0xd0) #define TSENS_8994_EEPROM_REDUN_SEL(n) ((n) + 0x464) #define TSENS_REDUN_REGION1_EEPROM(n) ((n) + 0x1c0) #define TSENS_REDUN_REGION2_EEPROM(n) ((n) + 0x1c4) #define TSENS_REDUN_REGION3_EEPROM(n) ((n) + 0x1cc) #define TSENS_REDUN_REGION4_EEPROM(n) ((n) + 0x440) #define TSENS_REDUN_REGION5_EEPROM(n) ((n) + 0x444) #define TSENS_CALIB_BIT_SIZE 3 /* TSENS calibration Mask data */ #define TSENS_BASE1_MASK 0xff #define TSENS0_POINT1_MASK 0x3f00 #define TSENS1_POINT1_MASK 0xfc000 #define TSENS2_POINT1_MASK 0x3f00000 #define TSENS3_POINT1_MASK 0xfc000000 #define TSENS4_POINT1_MASK 0x3f #define TSENS5_POINT1_MASK 0xfc0 #define TSENS6_POINT1_MASK 0x3f000 #define TSENS7_POINT1_MASK 0xfc0000 #define TSENS8_POINT1_MASK 0x3f000000 #define TSENS8_POINT1_MASK_BACKUP 0x3f #define TSENS9_POINT1_MASK 0x3f #define TSENS9_POINT1_MASK_BACKUP 0xfc0 #define TSENS10_POINT1_MASK 0xfc0 #define TSENS10_POINT1_MASK_BACKUP 0x3f000 #define TSENS_CAL_SEL_0_1 0xc0000000 #define TSENS_CAL_SEL_2 0x40000000 #define TSENS_CAL_SEL_SHIFT 30 #define TSENS_CAL_SEL_SHIFT_2 28 #define TSENS_ONE_POINT_CALIB 0x1 #define TSENS_ONE_POINT_CALIB_OPTION_2 0x2 #define TSENS_TWO_POINT_CALIB 0x3 #define TSENS0_POINT1_SHIFT 8 #define TSENS1_POINT1_SHIFT 14 #define TSENS2_POINT1_SHIFT 20 #define TSENS3_POINT1_SHIFT 26 #define TSENS5_POINT1_SHIFT 6 #define TSENS6_POINT1_SHIFT 12 #define TSENS7_POINT1_SHIFT 18 #define TSENS8_POINT1_SHIFT 24 #define TSENS9_POINT1_BACKUP_SHIFT 6 #define TSENS10_POINT1_SHIFT 6 #define TSENS10_POINT1_BACKUP_SHIFT 12 #define TSENS_POINT2_BASE_SHIFT 12 #define TSENS_POINT2_BASE_BACKUP_SHIFT 18 #define TSENS0_POINT2_SHIFT 20 #define TSENS0_POINT2_BACKUP_SHIFT 26 #define TSENS1_POINT2_SHIFT 26 #define TSENS2_POINT2_BACKUP_SHIFT 6 #define TSENS3_POINT2_SHIFT 6 #define TSENS3_POINT2_BACKUP_SHIFT 12 #define TSENS4_POINT2_SHIFT 12 #define TSENS4_POINT2_BACKUP_SHIFT 18 #define TSENS5_POINT2_SHIFT 18 #define TSENS5_POINT2_BACKUP_SHIFT 24 #define TSENS6_POINT2_SHIFT 24 #define TSENS7_POINT2_BACKUP_SHIFT 6 #define TSENS8_POINT2_SHIFT 6 #define TSENS8_POINT2_BACKUP_SHIFT 12 #define TSENS9_POINT2_SHIFT 12 #define TSENS9_POINT2_BACKUP_SHIFT 18 #define TSENS10_POINT2_SHIFT 18 #define TSENS10_POINT2_BACKUP_SHIFT 24 #define TSENS_BASE2_MASK 0xff000 #define TSENS_BASE2_BACKUP_MASK 0xfc0000 #define TSENS0_POINT2_MASK 0x3f00000 #define TSENS0_POINT2_BACKUP_MASK 0xfc000000 #define TSENS1_POINT2_MASK 0xfc000000 #define TSENS1_POINT2_BACKUP_MASK 0x3f #define TSENS2_POINT2_MASK 0x3f #define TSENS2_POINT2_BACKUP_MASK 0xfc0 #define TSENS3_POINT2_MASK 0xfc0 #define TSENS3_POINT2_BACKUP_MASK 0x3f000 #define TSENS4_POINT2_MASK 0x3f000 #define TSENS4_POINT2_BACKUP_MASK 0xfc0000 #define TSENS5_POINT2_MASK 0xfc0000 #define TSENS5_POINT2_BACKUP_MASK 0x3f000000 #define TSENS6_POINT2_MASK 0x3f000000 #define TSENS6_POINT2_BACKUP_MASK 0x3f #define TSENS7_POINT2_MASK 0x3f #define TSENS7_POINT2_BACKUP_MASK 0xfc0 #define TSENS8_POINT2_MASK 0xfc0 #define TSENS8_POINT2_BACKUP_MASK 0x3f000 #define TSENS9_POINT2_MASK 0x3f000 #define TSENS9_POINT2_BACKUP_MASK 0xfc0000 #define TSENS10_POINT2_MASK 0xfc0000 #define TSENS10_POINT2_BACKUP_MASK 0x3f000000 #define TSENS_8X26_BASE0_MASK 0x1fe000 #define TSENS0_8X26_POINT1_MASK 0x7e00000 #define TSENS1_8X26_POINT1_MASK 0x3f #define TSENS2_8X26_POINT1_MASK 0xfc0 #define TSENS3_8X26_POINT1_MASK 0x3f000 #define TSENS4_8X26_POINT1_MASK 0xfc0000 #define TSENS5_8X26_POINT1_MASK 0x3f000000 #define TSENS6_8X26_POINT1_MASK 0x3f00000 #define TSENS_8X26_TSENS_CAL_SEL 0xe0000000 #define TSENS_8X26_BASE1_MASK 0xff #define TSENS0_8X26_POINT2_MASK 0x3f00 #define TSENS1_8X26_POINT2_MASK 0xfc000 #define TSENS2_8X26_POINT2_MASK 0x3f00000 #define TSENS3_8X26_POINT2_MASK 0xfc000000 #define TSENS4_8X26_POINT2_MASK 0x3f00000 #define TSENS5_8X26_POINT2_MASK 0xfc000000 #define TSENS6_8X26_POINT2_MASK 0x7e0000 #define TSENS_8X26_CAL_SEL_SHIFT 29 #define TSENS_8X26_BASE0_SHIFT 13 #define TSENS0_8X26_POINT1_SHIFT 21 #define TSENS2_8X26_POINT1_SHIFT 6 #define TSENS3_8X26_POINT1_SHIFT 12 #define TSENS4_8X26_POINT1_SHIFT 18 #define TSENS5_8X26_POINT1_SHIFT 24 #define TSENS6_8X26_POINT1_SHIFT 20 #define TSENS0_8X26_POINT2_SHIFT 8 #define TSENS1_8X26_POINT2_SHIFT 14 #define TSENS2_8X26_POINT2_SHIFT 20 #define TSENS3_8X26_POINT2_SHIFT 26 #define TSENS4_8X26_POINT2_SHIFT 20 #define TSENS5_8X26_POINT2_SHIFT 26 #define TSENS6_8X26_POINT2_SHIFT 17 #define TSENS_8X10_CAL_SEL_SHIFT 28 #define TSENS_8X10_BASE1_SHIFT 8 #define TSENS0_8X10_POINT1_SHIFT 16 #define TSENS0_8X10_POINT2_SHIFT 22 #define TSENS1_8X10_POINT2_SHIFT 6 #define TSENS_8X10_BASE0_MASK 0xff #define TSENS_8X10_BASE1_MASK 0xff00 #define TSENS0_8X10_POINT1_MASK 0x3f0000 #define TSENS0_8X10_POINT2_MASK 0xfc00000 #define TSENS_8X10_TSENS_CAL_SEL 0x70000000 #define TSENS1_8X10_POINT1_MASK 0x3f #define TSENS1_8X10_POINT2_MASK 0xfc0 #define TSENS_8X10_REDUN_SEL_MASK 0x6000000 #define TSENS_8X10_REDUN_SEL_SHIFT 25 #define TSENS0_9900_POINT1_SHIFT 19 #define TSENS2_9900_POINT1_SHIFT 12 #define TSENS3_9900_POINT1_SHIFT 24 #define TSENS4_9900_POINT1_SHIFT 6 #define TSENS5_9900_POINT1_SHIFT 18 #define TSENS_9900_BASE1_MASK 0xff #define TSENS0_9900_POINT1_MASK 0x1f80000 #define TSENS1_9900_POINT1_MASK 0x3f #define TSENS2_9900_POINT1_MASK 0x3f000 #define TSENS3_9900_POINT1_MASK 0x3f000000 #define TSENS4_9900_POINT1_MASK 0xfc0 #define TSENS5_9900_POINT1_MASK 0xfc0000 #define TSENS6_9900_POINT1_MASK 0x3f #define TSENS_9900_BASE2_SHIFT 8 #define TSENS0_9900_POINT2_SHIFT 25 #define TSENS1_9900_POINT2_SHIFT 6 #define TSENS2_9900_POINT2_SHIFT 18 #define TSENS4_9900_POINT2_SHIFT 12 #define TSENS5_9900_POINT2_SHIFT 24 #define TSENS6_9900_POINT2_SHIFT 6 #define TSENS_9900_BASE2_MASK 0xff00 #define TSENS0_9900_POINT2_MASK 0x7e000000 #define TSENS1_9900_POINT2_MASK 0xfc0 #define TSENS2_9900_POINT2_MASK 0xfc0000 #define TSENS3_9900_POINT2_MASK 0x3f #define TSENS4_9900_POINT2_MASK 0x3f000 #define TSENS5_9900_POINT2_MASK 0x3f000000 #define TSENS6_9900_POINT2_MASK 0xfc0 #define TSENS_9900_CAL_SEL_SHIFT 16 #define TSENS_9900_TSENS_CAL_SEL 0x00070000 #define TSENS0_9010_POINT1_SHIFT 19 #define TSENS2_9010_POINT1_SHIFT 12 #define TSENS3_9010_POINT1_SHIFT 24 #define TSENS_9010_BASE1_MASK 0xff #define TSENS0_9010_POINT1_MASK 0x1f80000 #define TSENS1_9010_POINT1_MASK 0x3f #define TSENS2_9010_POINT1_MASK 0x3f000 #define TSENS_9010_BASE2_SHIFT 8 #define TSENS0_9010_POINT2_SHIFT 25 #define TSENS1_9010_POINT2_SHIFT 6 #define TSENS2_9010_POINT2_SHIFT 18 #define TSENS_9010_BASE2_MASK 0xff00 #define TSENS0_9010_POINT2_MASK 0x7e000000 #define TSENS1_9010_POINT2_MASK 0xfc0 #define TSENS2_9010_POINT2_MASK 0xfc0000 #define TSENS_9010_CAL_SEL_SHIFT 16 #define TSENS_9010_TSENS_CAL_SEL 0x00070000 #define TSENS_BIT_APPEND 0x3 #define TSENS_CAL_DEGC_POINT1 30 #define TSENS_CAL_DEGC_POINT2 120 #define TSENS_SLOPE_FACTOR 1000 /* TSENS register data */ #define TSENS_TRDY_RDY_MIN_TIME 2000 #define TSENS_TRDY_RDY_MAX_TIME 2100 #define TSENS_THRESHOLD_MAX_CODE 0x3ff #define TSENS_THRESHOLD_MIN_CODE 0x0 #define TSENS_GLOBAL_INIT_DATA 0x302f16c #define TSENS_S0_MAIN_CFG_INIT_DATA 0x1c3 #define TSENS_SN_REMOTE_CFG_DATA 0x11c3 #define TSENS_QFPROM_BACKUP_SEL 0x3 #define TSENS_QFPROM_BACKUP_REDUN_SEL 0xe0000000 #define TSENS_QFPROM_BACKUP_REDUN_SHIFT 29 #define TSENS_QFPROM_BACKUP_9900_REDUN_SEL 0x07000000 #define TSENS_QFPROM_BACKUP_9900_REDUN_SHIFT 24 #define TSENS_QFPROM_BACKUP_9010_REDUN_SEL 0x07000000 #define TSENS_QFPROM_BACKUP_9010_REDUN_SHIFT 24 #define TSENS_TORINO_BASE0 0x3ff #define TSENS_TORINO_BASE1 0xffc00 #define TSENS_TORINO_POINT0 0xf00000 #define TSENS_TORINO_POINT1 0xf0000000 #define TSENS_TORINO_POINT2 0xf0 #define TSENS_TORINO_POINT3 0xf000 #define TSENS_TORINO_POINT4 0xf00000 #define TSENS_TORINO_CALIB_PT 0x70000000 #define TSENS_TORINO_BASE1_SHIFT 10 #define TSENS_TORINO_POINT0_SHIFT 20 #define TSENS_TORINO_POINT1_SHIFT 28 #define TSENS_TORINO_POINT2_SHIFT 4 #define TSENS_TORINO_POINT3_SHIFT 12 #define TSENS_TORINO_POINT4_SHIFT 20 #define TSENS_TORINO_CALIB_SHIFT 28 #define TSENS_TYPE0 0 #define TSENS_TYPE2 2 #define TSENS_TYPE3 3 #define TSENS_8916_BASE0_MASK 0x0000007f #define TSENS_8916_BASE1_MASK 0xfe000000 #define TSENS0_8916_POINT1_MASK 0x00000f80 #define TSENS1_8916_POINT1_MASK 0x003e0000 #define TSENS2_8916_POINT1_MASK 0xf8000000 #define TSENS3_8916_POINT1_MASK 0x000003e0 #define TSENS4_8916_POINT1_MASK 0x000f8000 #define TSENS0_8916_POINT2_MASK 0x0001f000 #define TSENS1_8916_POINT2_MASK 0x07c00000 #define TSENS2_8916_POINT2_MASK 0x0000001f #define TSENS3_8916_POINT2_MASK 0x00007c00 #define TSENS4_8916_POINT2_MASK 0x01f00000 #define TSENS_8916_TSENS_CAL_SEL 0xe0000000 #define TSENS_8916_CAL_SEL_SHIFT 29 #define TSENS_8916_BASE1_SHIFT 25 #define TSENS0_8916_POINT1_SHIFT 7 #define TSENS1_8916_POINT1_SHIFT 17 #define TSENS2_8916_POINT1_SHIFT 27 #define TSENS3_8916_POINT1_SHIFT 5 #define TSENS4_8916_POINT1_SHIFT 15 #define TSENS0_8916_POINT2_SHIFT 12 #define TSENS1_8916_POINT2_SHIFT 22 #define TSENS3_8916_POINT2_SHIFT 10 #define TSENS4_8916_POINT2_SHIFT 20 #define TSENS_VALID_CNT_2 2 #define TSENS_8939_BASE0_MASK 0x000000ff #define TSENS_8939_BASE1_MASK 0xff000000 #define TSENS0_8939_POINT1_MASK 0x000001f8 #define TSENS1_8939_POINT1_MASK 0x001f8000 #define TSENS2_8939_POINT1_MASK_0_4 0xf8000000 #define TSENS2_8939_POINT1_MASK_5 0x00000001 #define TSENS3_8939_POINT1_MASK 0x00001f80 #define TSENS4_8939_POINT1_MASK 0x01f80000 #define TSENS5_8939_POINT1_MASK 0x00003f00 #define TSENS6_8939_POINT1_MASK 0x03f00000 #define TSENS7_8939_POINT1_MASK 0x0000003f #define TSENS8_8939_POINT1_MASK 0x0003f000 #define TSENS9_8939_POINT1_MASK 0x07e00000 #define TSENS0_8939_POINT2_MASK 0x00007e00 #define TSENS1_8939_POINT2_MASK 0x07e00000 #define TSENS2_8939_POINT2_MASK 0x0000007e #define TSENS3_8939_POINT2_MASK 0x0007e000 #define TSENS4_8939_POINT2_MASK 0x7e000000 #define TSENS5_8939_POINT2_MASK 0x000fc000 #define TSENS6_8939_POINT2_MASK 0xfc000000 #define TSENS7_8939_POINT2_MASK 0x00000fc0 #define TSENS8_8939_POINT2_MASK 0x00fc0000 #define TSENS9_8939_POINT2_MASK_0_4 0xf8000000 #define TSENS9_8939_POINT2_MASK_5 0x00002000 #define TSENS_8939_TSENS_CAL_SEL 0x7 #define TSENS_8939_CAL_SEL_SHIFT 0 #define TSENS_8939_BASE1_SHIFT 24 #define TSENS0_8939_POINT1_SHIFT 3 #define TSENS1_8939_POINT1_SHIFT 15 #define TSENS2_8939_POINT1_SHIFT_0_4 27 #define TSENS2_8939_POINT1_SHIFT_5 5 #define TSENS3_8939_POINT1_SHIFT 7 #define TSENS4_8939_POINT1_SHIFT 19 #define TSENS5_8939_POINT1_SHIFT 8 #define TSENS6_8939_POINT1_SHIFT 20 #define TSENS8_8939_POINT1_SHIFT 12 #define TSENS9_8939_POINT1_SHIFT 21 #define TSENS0_8939_POINT2_SHIFT 9 #define TSENS1_8939_POINT2_SHIFT 21 #define TSENS2_8939_POINT2_SHIFT 1 #define TSENS3_8939_POINT2_SHIFT 13 #define TSENS4_8939_POINT2_SHIFT 25 #define TSENS5_8939_POINT2_SHIFT 14 #define TSENS6_8939_POINT2_SHIFT 26 #define TSENS7_8939_POINT2_SHIFT 6 #define TSENS8_8939_POINT2_SHIFT 18 #define TSENS9_8939_POINT2_SHIFT_0_4 27 #define TSENS9_8939_POINT2_SHIFT_5 8 #define TSENS_NUM_SENSORS_V3 10 #define TSENS_BASE0_8994_MASK 0x3ff #define TSENS_BASE1_8994_MASK 0xffc00 #define TSENS_BASE1_8994_SHIFT 10 #define TSENS0_OFFSET_8994_MASK 0xf00000 #define TSENS0_OFFSET_8994_SHIFT 20 #define TSENS1_OFFSET_8994_MASK 0xf000000 #define TSENS1_OFFSET_8994_SHIFT 24 #define TSENS2_OFFSET_8994_MASK 0xf0000000 #define TSENS2_OFFSET_8994_SHIFT 28 #define TSENS3_OFFSET_8994_MASK 0xf #define TSENS4_OFFSET_8994_MASK 0xf0 #define TSENS4_OFFSET_8994_SHIFT 4 #define TSENS5_OFFSET_8994_MASK 0xf00 #define TSENS5_OFFSET_8994_SHIFT 8 #define TSENS6_OFFSET_8994_MASK 0xf000 #define TSENS6_OFFSET_8994_SHIFT 12 #define TSENS7_OFFSET_8994_MASK 0xf0000 #define TSENS7_OFFSET_8994_SHIFT 16 #define TSENS8_OFFSET_8994_MASK 0xf00000 #define TSENS8_OFFSET_8994_SHIFT 20 #define TSENS9_OFFSET_8994_MASK 0xf000000 #define TSENS9_OFFSET_8994_SHIFT 24 #define TSENS10_OFFSET_8994_MASK 0xf0000000 #define TSENS10_OFFSET_8994_SHIFT 28 #define TSENS11_OFFSET_8994_MASK 0xf #define TSENS12_OFFSET_8994_MASK 0xf0 #define TSENS12_OFFSET_8994_SHIFT 4 #define TSENS13_OFFSET_8994_MASK 0xf00 #define TSENS13_OFFSET_8994_SHIFT 8 #define TSENS14_OFFSET_8994_MASK 0xf000 #define TSENS14_OFFSET_8994_SHIFT 12 #define TSENS15_OFFSET_8994_MASK 0xf0000 #define TSENS15_OFFSET_8994_SHIFT 16 #define TSENS_8994_CAL_SEL_MASK 0x700000 #define TSENS_8994_CAL_SEL_SHIFT 20 #define TSENS_BASE0_8994_REDUN_MASK 0x7fe00000 #define TSENS_BASE0_8994_REDUN_MASK_SHIFT 21 #define TSENS_BASE1_BIT0_8994_REDUN_MASK 0x80000000 #define TSENS_BASE1_BIT0_SHIFT_COMPUTE 31 #define TSENS_BASE1_BIT1_9_8994_REDUN_MASK 0x1ff #define TSENS0_OFFSET_8994_REDUN_MASK 0x1e00 #define TSENS0_OFFSET_8994_REDUN_SHIFT 9 #define TSENS1_OFFSET_8994_REDUN_MASK 0x1e000 #define TSENS1_OFFSET_8994_REDUN_SHIFT 13 #define TSENS2_OFFSET_8994_REDUN_MASK 0x1e0000 #define TSENS2_OFFSET_8994_REDUN_SHIFT 17 #define TSENS3_OFFSET_8994_REDUN_MASK 0x1e00000 #define TSENS3_OFFSET_8994_REDUN_SHIFT 21 #define TSENS4_OFFSET_8994_REDUN_MASK 0x1e000000 #define TSENS4_OFFSET_8994_REDUN_SHIFT 25 #define TSENS5_OFFSET_8994_REDUN_MASK_BIT0_2 0xe0000000 #define TSENS5_OFFSET_8994_REDUN_SHIFT_BIT0_2 29 #define TSENS5_OFFSET_8994_REDUN_MASK_BIT3 0x800000 #define TSENS5_OFFSET_8994_REDUN_SHIFT_BIT3 23 #define TSENS6_OFFSET_8994_REDUN_MASK 0xf000000 #define TSENS6_OFFSET_8994_REDUN_SHIFT 24 #define TSENS7_OFFSET_8994_REDUN_MASK 0xf0000000 #define TSENS7_OFFSET_8994_REDUN_SHIFT 28 #define TSENS8_OFFSET_8994_REDUN_MASK 0xf #define TSENS9_OFFSET_8994_REDUN_MASK 0xf0 #define TSENS9_OFFSET_8994_REDUN_SHIFT 4 #define TSENS10_OFFSET_8994_REDUN_MASK 0xf00 #define TSENS10_OFFSET_8994_REDUN_SHIFT 8 #define TSENS11_OFFSET_8994_REDUN_MASK 0xf000 #define TSENS11_OFFSET_8994_REDUN_SHIFT 12 #define TSENS12_OFFSET_8994_REDUN_MASK 0xf0000 #define TSENS12_OFFSET_8994_REDUN_SHIFT 16 #define TSENS13_OFFSET_8994_REDUN_MASK 0xf00000 #define TSENS13_OFFSET_8994_REDUN_SHIFT 20 #define TSENS14_OFFSET_8994_REDUN_MASK 0xf000000 #define TSENS14_OFFSET_8994_REDUN_SHIFT 24 #define TSENS15_OFFSET_8994_REDUN_MASK 0xf0000000 #define TSENS15_OFFSET_8994_REDUN_SHIFT 28 #define TSENS_8994_REDUN_SEL_MASK 0x7 #define TSENS_8994_CAL_SEL_REDUN_MASK 0xe0000000 #define TSENS_8994_CAL_SEL_REDUN_SHIFT 29 #define TSENS_MSM8909_BASE0_MASK 0x000000ff #define TSENS_MSM8909_BASE1_MASK 0x0000ff00 #define TSENS0_MSM8909_POINT1_MASK 0x0000003f #define TSENS1_MSM8909_POINT1_MASK 0x0003f000 #define TSENS2_MSM8909_POINT1_MASK 0x3f000000 #define TSENS3_MSM8909_POINT1_MASK 0x000003f0 #define TSENS4_MSM8909_POINT1_MASK 0x003f0000 #define TSENS0_MSM8909_POINT2_MASK 0x00000fc0 #define TSENS1_MSM8909_POINT2_MASK 0x00fc0000 #define TSENS2_MSM8909_POINT2_MASK_0_1 0xc0000000 #define TSENS2_MSM8909_POINT2_MASK_2_5 0x0000000f #define TSENS3_MSM8909_POINT2_MASK 0x0000fc00 #define TSENS4_MSM8909_POINT2_MASK 0x0fc00000 #define TSENS_MSM8909_TSENS_CAL_SEL 0x00070000 #define TSENS_MSM8909_CAL_SEL_SHIFT 16 #define TSENS_MSM8909_BASE1_SHIFT 8 #define TSENS1_MSM8909_POINT1_SHIFT 12 #define TSENS2_MSM8909_POINT1_SHIFT 24 #define TSENS3_MSM8909_POINT1_SHIFT 4 #define TSENS4_MSM8909_POINT1_SHIFT 16 #define TSENS0_MSM8909_POINT2_SHIFT 6 #define TSENS1_MSM8909_POINT2_SHIFT 18 #define TSENS2_MSM8909_POINT2_SHIFT_0_1 30 #define TSENS2_MSM8909_POINT2_SHIFT_2_5 2 #define TSENS3_MSM8909_POINT2_SHIFT 10 #define TSENS4_MSM8909_POINT2_SHIFT 22 #define TSENS_MSM8909_D30_WA_S1 10 #define TSENS_MSM8909_D30_WA_S3 9 #define TSENS_MSM8909_D30_WA_S4 8 #define TSENS_MSM8909_D120_WA_S1 6 #define TSENS_MSM8909_D120_WA_S3 9 #define TSENS_MSM8909_D120_WA_S4 10 #define TSENS_9640_CAL_SEL 0x700 #define TSENS_9640_CAL_SEL_SHIFT 8 #define TSENS_BASE0_9640_MASK 0x3ff #define TSENS_BASE1_9640_MASK 0xffc00 #define TSENS_BASE1_9640_SHIFT 10 #define TSENS0_OFFSET_9640_MASK 0xf00000 #define TSENS0_OFFSET_9640_SHIFT 20 #define TSENS1_OFFSET_9640_MASK 0xf000000 #define TSENS1_OFFSET_9640_SHIFT 24 #define TSENS2_OFFSET_9640_MASK 0xf0000000 #define TSENS2_OFFSET_9640_SHIFT 28 #define TSENS3_OFFSET_9640_MASK 0xf #define TSENS4_OFFSET_9640_MASK 0xf0 #define TSENS4_OFFSET_9640_SHIFT 4 #define TSENS_MSM8952_BASE0_MASK 0x000000ff #define TSENS_MSM8952_BASE1_MASK 0xff000000 #define TSENS0_MSM8952_POINT1_MASK 0x000001f8 #define TSENS1_MSM8952_POINT1_MASK 0x001f8000 #define TSENS2_MSM8952_POINT1_MASK_0_4 0xf8000000 #define TSENS2_MSM8952_POINT1_MASK_5 0x00000001 #define TSENS3_MSM8952_POINT1_MASK 0x00001f80 #define TSENS4_MSM8952_POINT1_MASK 0x01f80000 #define TSENS5_MSM8952_POINT1_MASK 0x00003f00 #define TSENS6_MSM8952_POINT1_MASK 0x03f00000 #define TSENS7_MSM8952_POINT1_MASK 0x0000003f #define TSENS8_MSM8952_POINT1_MASK 0x0003f000 #define TSENS9_MSM8952_POINT1_MASK 0x0000003f #define TSENS10_MSM8952_POINT1_MASK 0x0003f000 #define TSENS0_MSM8952_POINT2_MASK 0x00007e00 #define TSENS1_MSM8952_POINT2_MASK 0x07e00000 #define TSENS2_MSM8952_POINT2_MASK 0x0000007e #define TSENS3_MSM8952_POINT2_MASK 0x0007e000 #define TSENS4_MSM8952_POINT2_MASK 0x7e000000 #define TSENS5_MSM8952_POINT2_MASK 0x000fc000 #define TSENS6_MSM8952_POINT2_MASK 0xfc000000 #define TSENS7_MSM8952_POINT2_MASK 0x00000fc0 #define TSENS8_MSM8952_POINT2_MASK 0x00fc0000 #define TSENS9_MSM8952_POINT2_MASK 0x00000fc0 #define TSENS10_MSM8952_POINT2_MASK 0x00fc0000 #define TSENS_MSM8952_TSENS_CAL_SEL 0x00000007 #define TSENS_MSM8952_BASE1_SHIFT 24 #define TSENS0_MSM8952_POINT1_SHIFT 3 #define TSENS1_MSM8952_POINT1_SHIFT 15 #define TSENS2_MSM8952_POINT1_SHIFT_0_4 27 #define TSENS2_MSM8952_POINT1_SHIFT_5 5 #define TSENS3_MSM8952_POINT1_SHIFT 7 #define TSENS4_MSM8952_POINT1_SHIFT 19 #define TSENS5_MSM8952_POINT1_SHIFT 8 #define TSENS6_MSM8952_POINT1_SHIFT 20 #define TSENS8_MSM8952_POINT1_SHIFT 12 #define TSENS10_MSM8952_POINT1_SHIFT 12 #define TSENS0_MSM8952_POINT2_SHIFT 9 #define TSENS1_MSM8952_POINT2_SHIFT 21 #define TSENS2_MSM8952_POINT2_SHIFT 1 #define TSENS3_MSM8952_POINT2_SHIFT 13 #define TSENS4_MSM8952_POINT2_SHIFT 25 #define TSENS5_MSM8952_POINT2_SHIFT 14 #define TSENS6_MSM8952_POINT2_SHIFT 26 #define TSENS7_MSM8952_POINT2_SHIFT 6 #define TSENS8_MSM8952_POINT2_SHIFT 18 #define TSENS9_MSM8952_POINT2_SHIFT 6 #define TSENS10_MSM8952_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 enum tsens_calib_fuse_map_type { TSENS_CALIB_FUSE_MAP_8974 = 0, TSENS_CALIB_FUSE_MAP_8X26, TSENS_CALIB_FUSE_MAP_8X10, TSENS_CALIB_FUSE_MAP_9900, TSENS_CALIB_FUSE_MAP_9010, TSENS_CALIB_FUSE_MAP_9630, TSENS_CALIB_FUSE_MAP_8916, TSENS_CALIB_FUSE_MAP_8939, TSENS_CALIB_FUSE_MAP_8994, TSENS_CALIB_FUSE_MAP_MSM8909, TSENS_CALIB_FUSE_MAP_MDM9640, TSENS_CALIB_FUSE_MAP_8992, TSENS_CALIB_FUSE_MAP_MSM8952, TSENS_CALIB_FUSE_MAP_GENERIC_A, TSENS_CALIB_FUSE_MAP_NUM, }; /* Trips: warm and cool */ enum tsens_trip_type { TSENS_TRIP_WARM = 0, TSENS_TRIP_COOL, TSENS_TRIP_NUM, }; #define TSENS_WRITABLE_TRIPS_MASK ((1 << TSENS_TRIP_NUM) - 1) struct tsens_tm_device_sensor { struct thermal_zone_device *tz_dev; 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; int offset; int calib_data_point1; int calib_data_point2; uint32_t slope_mul_tsens_factor; }; struct tsens_dbg_counter { uint32_t dbg_count[10]; uint32_t idx; unsigned long long time_stmp[10]; }; struct tsens_sensor_dbg_info { unsigned long temp[10]; uint32_t idx; unsigned long long time_stmp[10]; }; struct mask_info { uint32_t id; uint32_t addr_offset; uint32_t mask; uint32_t mask_shift; uint32_t mask_bits; }; struct tsens_mtc_sysfs { uint32_t zone_log; int zone_mtc; int th1; int th2; }; struct tsens_tm_device { struct platform_device *pdev; bool is_ready; bool prev_reading_avail; bool calibration_less_mode; bool tsens_local_init; int tsens_factor; uint32_t tsens_num_sensor; int tsens_irq; void *tsens_addr; void *tsens_calib_addr; int tsens_len; int calib_len; struct resource *res_tsens_mem; struct resource *res_calib_mem; struct work_struct tsens_work; uint32_t calib_mode; uint32_t tsens_type; uint32_t tsens_no_of_base; uint32_t tsens_base_bit_size; struct mask_info *tsens_base_mask; uint32_t tsens_calib_mask_info; struct mask_info *tsens_calib_mask; uint32_t tsens_sensor_bit_size; uint32_t tsens_sensor_point1_masks; uint32_t tsens_sensor_point2_masks; struct mask_info *tsens_point1_mask; struct mask_info *tsens_point2_mask; bool tsens_valid_status_check; struct tsens_dbg_counter tsens_thread_iq_dbg; struct tsens_sensor_dbg_info sensor_dbg_info[16]; struct tsens_mtc_sysfs mtcsys; struct tsens_tm_device_sensor sensor[0]; }; struct tsens_tm_device *tmdev; 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,fsm9010-tsens", .data = (void *)TSENS_CALIB_FUSE_MAP_9010, }, { .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,mdm9640-tsens", .data = (void *)TSENS_CALIB_FUSE_MAP_MDM9640, }, { .compatible = "qcom,msm8992-tsens", .data = (void *)TSENS_CALIB_FUSE_MAP_8992, }, { .compatible = "qcom,msm8952-tsens", .data = (void *)TSENS_CALIB_FUSE_MAP_MSM8952, }, { .compatible = "qcom,msm8976-tsens", .data = (void *)TSENS_CALIB_FUSE_MAP_GENERIC_A, }, { .compatible = "qcom,mdm9640v2-tsens", .data = (void *)TSENS_CALIB_FUSE_MAP_MDM9640, }, {} }; static ssize_t zonemask_show(struct device *dev, struct device_attribute *attr, char *buf) { 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; 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"); return -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]; 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; ret = sscanf(buf, "%d", &tmdev->mtcsys.zone_log); if (ret != TSENS_ZONELOG_PARAMS) { 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), }; 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; } int tsens_is_ready() { if (!tmdev) return -EPROBE_DEFER; else return tmdev->is_ready; } EXPORT_SYMBOL(tsens_is_ready); int tsens_get_sw_id_mapping(int sensor_hw_num, int *sensor_sw_idx) { 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; id_found = true; } i++; } if (!id_found) return -EINVAL; return 0; } EXPORT_SYMBOL(tsens_get_sw_id_mapping); int tsens_get_hw_id_mapping(int sensor_sw_id, int *sensor_hw_num) { 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_sw_id == tmdev->sensor[i].sensor_sw_id) { *sensor_hw_num = tmdev->sensor[i].sensor_hw_num; id_found = true; } i++; } if (!id_found) return -EINVAL; return 0; } EXPORT_SYMBOL(tsens_get_hw_id_mapping); static int tsens_tz_code_to_degc(int adc_code, int sensor_sw_id) { int degc, num, den, idx; idx = sensor_sw_id; num = ((adc_code * tmdev->tsens_factor) - tmdev->sensor[idx].offset); den = (int) tmdev->sensor[idx].slope_mul_tsens_factor; if (num > 0) degc = ((num + (den/2))/den); else if (num < 0) degc = ((num - (den/2))/den); else degc = num/den; pr_debug("raw_code:0x%x, sensor_num:%d, degc:%d, offset:%d\n", adc_code, idx, degc, tmdev->sensor[idx].offset); return degc; } static int tsens_tz_degc_to_code(int degc, int idx) { int code = ((degc * tmdev->sensor[idx].slope_mul_tsens_factor) + tmdev->sensor[idx].offset)/tmdev->tsens_factor; if (code > TSENS_THRESHOLD_MAX_CODE) code = TSENS_THRESHOLD_MAX_CODE; else if (code < TSENS_THRESHOLD_MIN_CODE) code = TSENS_THRESHOLD_MIN_CODE; pr_debug("raw_code:0x%x, sensor_num:%d, degc:%d\n", code, idx, degc); return code; } static void msm_tsens_get_temp(int sensor_hw_num, unsigned long *temp) { unsigned int code; void __iomem *sensor_addr; void __iomem *trdy_addr; int sensor_sw_id = -EINVAL, rc = 0, last_temp = 0, last_temp2 = 0; int last_temp3 = 0; bool last_temp_valid = false, last_temp2_valid = false; bool last_temp3_valid = false; if (tmdev->tsens_type == TSENS_TYPE2) { trdy_addr = TSENS2_TRDY_ADDR(tmdev->tsens_addr); sensor_addr = TSENS2_SN_STATUS_ADDR(tmdev->tsens_addr); } else if (tmdev->tsens_type == TSENS_TYPE3) { trdy_addr = TSENS3_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); } if ((!tmdev->prev_reading_avail) && !tmdev->tsens_valid_status_check) { while (!((readl_relaxed(trdy_addr)) & TSENS_TRDY_MASK)) usleep_range(TSENS_TRDY_RDY_MIN_TIME, TSENS_TRDY_RDY_MAX_TIME); tmdev->prev_reading_avail = true; } code = readl_relaxed(sensor_addr + (sensor_hw_num << TSENS_STATUS_ADDR_OFFSET)); last_temp = code & TSENS_SN_STATUS_TEMP_MASK; if (tmdev->tsens_valid_status_check) { if (code & TSENS2_SN_STATUS_VALID_MASK) last_temp_valid = true; else { code = readl_relaxed(sensor_addr + (sensor_hw_num << TSENS_STATUS_ADDR_OFFSET)); last_temp2 = code & TSENS_SN_STATUS_TEMP_MASK; if (code & TSENS2_SN_STATUS_VALID_MASK) { last_temp = last_temp2; last_temp2_valid = true; } else { code = readl_relaxed(sensor_addr + (sensor_hw_num << TSENS_STATUS_ADDR_OFFSET)); last_temp3 = code & TSENS_SN_STATUS_TEMP_MASK; if (code & TSENS2_SN_STATUS_VALID_MASK) { last_temp = last_temp3; last_temp3_valid = true; } } } } if ((tmdev->tsens_valid_status_check) && (!last_temp_valid && !last_temp2_valid && !last_temp3_valid)) { if (last_temp == last_temp2) last_temp = last_temp2; else if (last_temp2 == last_temp3) last_temp = last_temp3; } /* 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); if (rc < 0) { pr_err("tsens mapping index not found\n"); return; } *temp = tsens_tz_code_to_degc(last_temp, sensor_sw_id); trace_tsens_read(*temp, sensor_hw_num); } static int tsens_tz_get_temp(struct thermal_zone_device *thermal, unsigned long *temp) { struct tsens_tm_device_sensor *tm_sensor = thermal->devdata; uint32_t idx = 0; if (!tm_sensor || tm_sensor->mode != THERMAL_DEVICE_ENABLED || !temp) return -EINVAL; msm_tsens_get_temp(tm_sensor->sensor_hw_num, temp); 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(); 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) { if (tsens_is_ready() <= 0) { pr_debug("TSENS early init not done\n"); return -EPROBE_DEFER; } msm_tsens_get_temp(device->sensor_num, temp); return 0; } EXPORT_SYMBOL(tsens_get_temp); int tsens_get_max_sensor_num(uint32_t *tsens_num_sensors) { if (tsens_is_ready() <= 0) { pr_debug("TSENS early init not done\n"); return -EPROBE_DEFER; } *tsens_num_sensors = tmdev->tsens_num_sensor; return 0; } EXPORT_SYMBOL(tsens_get_max_sensor_num); int tsens_set_mtc_zone_sw_mask(unsigned int zone , unsigned int th1_enable, unsigned int th2_enable) { unsigned int reg_cntl; if (zone > TSENS_NUM_MTC_ZONES_SUPPORT) return -EINVAL; if (th1_enable && th2_enable) writel_relaxed(TSENS_MTC_IN_EFFECT, (TSENS_MTC_ZONE0_SW_MASK_ADDR (tmdev->tsens_addr) + (zone * TSENS_SN_ADDR_OFFSET))); if (!th1_enable && !th2_enable) writel_relaxed(TSENS_MTC_DISABLE, (TSENS_MTC_ZONE0_SW_MASK_ADDR (tmdev->tsens_addr) + (zone * TSENS_SN_ADDR_OFFSET))); if (th1_enable && !th2_enable) writel_relaxed(TSENS_TH1_MTC_IN_EFFECT, (TSENS_MTC_ZONE0_SW_MASK_ADDR (tmdev->tsens_addr) + (zone * TSENS_SN_ADDR_OFFSET))); if (!th1_enable && th2_enable) writel_relaxed(TSENS_TH2_MTC_IN_EFFECT, (TSENS_MTC_ZONE0_SW_MASK_ADDR (tmdev->tsens_addr) + (zone * TSENS_SN_ADDR_OFFSET))); reg_cntl = readl_relaxed((TSENS_MTC_ZONE0_SW_MASK_ADDR (tmdev->tsens_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; if (zone > TSENS_NUM_MTC_ZONES_SUPPORT) return -EINVAL; reg_cntl = readl_relaxed((TSENS_MTC_ZONE0_LOG (tmdev->tsens_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); static int tsens_tz_get_mode(struct thermal_zone_device *thermal, enum thermal_device_mode *mode) { struct tsens_tm_device_sensor *tm_sensor = thermal->devdata; if (!tm_sensor || !mode) return -EINVAL; *mode = tm_sensor->mode; return 0; } static int tsens_tz_get_trip_type(struct thermal_zone_device *thermal, int trip, enum thermal_trip_type *type) { struct tsens_tm_device_sensor *tm_sensor = thermal->devdata; if (!tm_sensor || trip < 0 || !type) return -EINVAL; switch (trip) { case TSENS_TRIP_WARM: *type = THERMAL_TRIP_CONFIGURABLE_HI; break; case TSENS_TRIP_COOL: *type = THERMAL_TRIP_CONFIGURABLE_LOW; break; default: return -EINVAL; } return 0; } static int tsens_tz_activate_trip_type(struct thermal_zone_device *thermal, int trip, enum thermal_trip_activation_mode mode) { struct tsens_tm_device_sensor *tm_sensor = thermal->devdata; unsigned int reg_cntl, code, hi_code, lo_code, mask; if (!tm_sensor || trip < 0) return -EINVAL; lo_code = TSENS_THRESHOLD_MIN_CODE; hi_code = TSENS_THRESHOLD_MAX_CODE; reg_cntl = readl_relaxed((TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR (tmdev->tsens_addr) + (tm_sensor->sensor_hw_num * TSENS_SN_ADDR_OFFSET))); switch (trip) { case TSENS_TRIP_WARM: code = (reg_cntl & TSENS_UPPER_THRESHOLD_MASK) >> TSENS_UPPER_THRESHOLD_SHIFT; mask = TSENS_UPPER_STATUS_CLR; if (!(reg_cntl & TSENS_LOWER_STATUS_CLR)) lo_code = (reg_cntl & TSENS_LOWER_THRESHOLD_MASK); break; case TSENS_TRIP_COOL: code = (reg_cntl & TSENS_LOWER_THRESHOLD_MASK); mask = TSENS_LOWER_STATUS_CLR; if (!(reg_cntl & TSENS_UPPER_STATUS_CLR)) hi_code = (reg_cntl & TSENS_UPPER_THRESHOLD_MASK) >> TSENS_UPPER_THRESHOLD_SHIFT; break; default: return -EINVAL; } if (mode == THERMAL_TRIP_ACTIVATION_DISABLED) writel_relaxed(reg_cntl | mask, (TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR (tmdev->tsens_addr) + (tm_sensor->sensor_hw_num * TSENS_SN_ADDR_OFFSET))); 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))); } mb(); return 0; } static int tsens_tz_get_trip_temp(struct thermal_zone_device *thermal, int trip, unsigned long *temp) { struct tsens_tm_device_sensor *tm_sensor = thermal->devdata; unsigned int reg; int sensor_sw_id = -EINVAL, rc = 0; if (!tm_sensor || trip < 0 || !temp) return -EINVAL; reg = readl_relaxed(TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR (tmdev->tsens_addr) + (tm_sensor->sensor_hw_num * TSENS_SN_ADDR_OFFSET)); switch (trip) { case TSENS_TRIP_WARM: reg = (reg & TSENS_UPPER_THRESHOLD_MASK) >> TSENS_UPPER_THRESHOLD_SHIFT; break; case TSENS_TRIP_COOL: reg = (reg & TSENS_LOWER_THRESHOLD_MASK); break; default: return -EINVAL; } rc = tsens_get_sw_id_mapping(tm_sensor->sensor_hw_num, &sensor_sw_id); if (rc < 0) { pr_err("tsens mapping index not found\n"); return rc; } *temp = tsens_tz_code_to_degc(reg, sensor_sw_id); return 0; } static int tsens_tz_notify(struct thermal_zone_device *thermal, int count, enum thermal_trip_type type) { /* Critical temperature threshold are enabled and will * shutdown the device once critical thresholds are crossed. */ pr_debug("%s debug\n", __func__); return 1; } static int tsens_tz_set_trip_temp(struct thermal_zone_device *thermal, int trip, unsigned long 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; if (!tm_sensor || trip < 0) return -EINVAL; rc = tsens_get_sw_id_mapping(tm_sensor->sensor_hw_num, &sensor_sw_id); 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); if (!tm_sensor || trip < 0) return -EINVAL; lo_code = TSENS_THRESHOLD_MIN_CODE; hi_code = TSENS_THRESHOLD_MAX_CODE; reg_cntl = readl_relaxed(TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR (tmdev->tsens_addr) + (tm_sensor->sensor_hw_num * TSENS_SN_ADDR_OFFSET)); switch (trip) { case TSENS_TRIP_WARM: 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: reg_cntl &= ~TSENS_LOWER_THRESHOLD_MASK; if (!(reg_cntl & TSENS_UPPER_STATUS_CLR)) hi_code = (reg_cntl & TSENS_UPPER_THRESHOLD_MASK) >> TSENS_UPPER_THRESHOLD_SHIFT; break; default: return -EINVAL; } writel_relaxed(reg_cntl | code, (TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR (tmdev->tsens_addr) + (tm_sensor->sensor_hw_num * TSENS_SN_ADDR_OFFSET))); mb(); return 0; } static struct thermal_zone_device_ops tsens_thermal_zone_ops = { .get_temp = tsens_tz_get_temp, .get_mode = tsens_tz_get_mode, .get_trip_type = tsens_tz_get_trip_type, .activate_trip_type = tsens_tz_activate_trip_type, .get_trip_temp = tsens_tz_get_trip_temp, .set_trip_temp = tsens_tz_set_trip_temp, .notify = tsens_tz_notify, }; static irqreturn_t tsens_irq_thread(int irq, void *data) { struct tsens_tm_device *tm = data; unsigned int i, status, threshold; void __iomem *sensor_status_addr; void __iomem *sensor_status_ctrl_addr; int sensor_sw_id = -EINVAL, rc = 0; uint32_t idx = 0; if ((tmdev->tsens_type == TSENS_TYPE2) || (tmdev->tsens_type == TSENS_TYPE3)) sensor_status_addr = TSENS2_SN_STATUS_ADDR(tmdev->tsens_addr); else sensor_status_addr = TSENS_S0_STATUS_ADDR(tmdev->tsens_addr); sensor_status_ctrl_addr = TSENS_S0_UPPER_LOWER_STATUS_CTRL_ADDR(tmdev->tsens_addr); for (i = 0; i < tm->tsens_num_sensor; i++) { bool upper_thr = false, lower_thr = false; uint32_t addr_offset; addr_offset = tm->sensor[i].sensor_hw_num * TSENS_SN_ADDR_OFFSET; status = readl_relaxed(sensor_status_addr + addr_offset); threshold = readl_relaxed(sensor_status_ctrl_addr + addr_offset); 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)); upper_thr = true; } 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)); lower_thr = true; } if (upper_thr || lower_thr) { unsigned long 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)); if (upper_thr) trace_tsens_threshold_hit( tsens_tz_code_to_degc((threshold & TSENS_UPPER_THRESHOLD_MASK) >> TSENS_UPPER_THRESHOLD_SHIFT, sensor_sw_id), tm->sensor[i].sensor_hw_num); else trace_tsens_threshold_clear( tsens_tz_code_to_degc((threshold & TSENS_LOWER_THRESHOLD_MASK), sensor_sw_id), 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++; mb(); return IRQ_HANDLED; } static void tsens_hw_init(void) { unsigned int reg_cntl = 0, sensor_en = 0; unsigned int i; if (tmdev->tsens_local_init && tmdev->tsens_type == TSENS_TYPE0) { writel_relaxed(reg_cntl, TSENS_CTRL_ADDR(tmdev->tsens_addr)); writel_relaxed(reg_cntl | TSENS_SW_RST, TSENS_CTRL_ADDR(tmdev->tsens_addr)); reg_cntl |= (TSENS_62_5_MS_MEAS_PERIOD << TSENS_MEAS_PERIOD_SHIFT); for (i = 0; i < tmdev->tsens_num_sensor; i++) sensor_en |= (1 << tmdev->sensor[i].sensor_hw_num); sensor_en <<= TSENS_SENSOR0_SHIFT; reg_cntl |= (sensor_en | TSENS_EN); writel_relaxed(reg_cntl, TSENS_CTRL_ADDR(tmdev->tsens_addr)); writel_relaxed(TSENS_GLOBAL_INIT_DATA, TSENS_GLOBAL_CONFIG(tmdev->tsens_addr)); writel_relaxed(TSENS_S0_MAIN_CFG_INIT_DATA, TSENS_S0_MAIN_CONFIG(tmdev->tsens_addr)); for (i = 0; i < tmdev->tsens_num_sensor; i++) { writel_relaxed(TSENS_SN_REMOTE_CFG_DATA, TSENS_SN_REMOTE_CONFIG(tmdev->tsens_addr) + (tmdev->sensor[i].sensor_hw_num * TSENS_SN_ADDR_OFFSET)); } pr_debug("Local TSENS control initialization\n"); } writel_relaxed(TSENS_INTERRUPT_EN, TSENS_UPPER_LOWER_INTERRUPT_CTRL(tmdev->tsens_addr)); } static void tsens_calculate_data(uint32_t *data, uint32_t count, uint32_t no_of_bits, struct mask_info *mask) { uint32_t id = 0, i = 0, temp = 0; for (i = 0; i < count; i++) { id = mask[i].id; temp = readl_relaxed(tmdev->tsens_calib_addr + mask[i].addr_offset); data[id] = (temp & mask[i].mask) >> mask[i].mask_shift; if (mask[i].mask_bits != no_of_bits) { temp = readl_relaxed(tmdev->tsens_calib_addr + mask[i + 1].addr_offset); data[id] |= (((temp & mask[i + 1].mask) >> mask[i + 1].mask_shift) << mask[i].mask_bits); i = i + 1; } } } static int tsens_generic_dt_calib_type_a(void) { int i = 0, tsens_calibration_mode = 0; uint32_t tsens_num_sensor = tmdev->tsens_num_sensor; uint32_t calib_tsens_point1_data[tsens_num_sensor]; uint32_t calib_tsens_point2_data[tsens_num_sensor]; uint32_t tsens_base_data[2] = {0, 0}; struct mask_info *tsens_calib_mask = tmdev->tsens_calib_mask; struct mask_info *tsens_base_mask = tmdev->tsens_base_mask; uint32_t tsens_sensor_point1_masks = tmdev->tsens_sensor_point1_masks; uint32_t tsens_sensor_point2_masks = tmdev->tsens_sensor_point2_masks; uint32_t tsens_bit_size = tmdev->tsens_sensor_bit_size; uint32_t no_of_base = tmdev->tsens_no_of_base; uint32_t base_bit_size = tmdev->tsens_base_bit_size; struct mask_info *tsens_point1_mask = tmdev->tsens_point1_mask; struct mask_info *tsens_point2_mask = tmdev->tsens_point2_mask; for (i = 0; i < tsens_num_sensor; i++) { calib_tsens_point1_data[i] = 0; calib_tsens_point2_data[i] = 0; } if (!tmdev->calibration_less_mode) tsens_calculate_data(&tsens_calibration_mode, tmdev->tsens_calib_mask_info, TSENS_CALIB_BIT_SIZE, tsens_calib_mask); tsens_calculate_data(tsens_base_data, no_of_base, base_bit_size, tsens_base_mask); if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB) || (tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) tsens_calculate_data(calib_tsens_point1_data, tsens_sensor_point1_masks, tsens_bit_size, tsens_point1_mask); if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) tsens_calculate_data(calib_tsens_point2_data, tsens_sensor_point2_masks, tsens_bit_size, tsens_point2_mask); if (tsens_calibration_mode == 0) { pr_debug("TSENS is calibrationless mode\n"); for (i = 0; i < tsens_num_sensor; i++) { calib_tsens_point2_data[i] = 780; calib_tsens_point1_data[i] = 500; } } if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) || (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) { for (i = 0; i < tsens_num_sensor; i++) calib_tsens_point1_data[i] = ((tsens_base_data[0] + calib_tsens_point1_data[i]) << (10 - base_bit_size)); } if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { pr_debug("two point calibration calculation\n"); for (i = 0; i < tsens_num_sensor; i++) calib_tsens_point2_data[i] = ((tsens_base_data[1] + calib_tsens_point2_data[i]) << (10 - base_bit_size)); } 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(void) { 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_MSM8952_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_MSM8952_BASE0_MASK); tsens0_point1 = (calib_data[0] & TSENS0_MSM8952_POINT1_MASK) >> TSENS0_MSM8952_POINT1_SHIFT; tsens1_point1 = (calib_data[0] & TSENS1_MSM8952_POINT1_MASK) >> TSENS1_MSM8952_POINT1_SHIFT; tsens2_point1 = (calib_data[0] & TSENS2_MSM8952_POINT1_MASK_0_4) >> TSENS2_MSM8952_POINT1_SHIFT_0_4; temp = (calib_data[1] & TSENS2_MSM8952_POINT1_MASK_5) << TSENS2_MSM8952_POINT1_SHIFT_5; tsens2_point1 |= temp; tsens3_point1 = (calib_data[1] & TSENS3_MSM8952_POINT1_MASK) >> TSENS3_MSM8952_POINT1_SHIFT; tsens4_point1 = (calib_data[1] & TSENS4_MSM8952_POINT1_MASK) >> TSENS4_MSM8952_POINT1_SHIFT; tsens5_point1 = (calib_data[2] & TSENS5_MSM8952_POINT1_MASK) >> TSENS5_MSM8952_POINT1_SHIFT; tsens6_point1 = (calib_data[2] & TSENS6_MSM8952_POINT1_MASK) >> TSENS6_MSM8952_POINT1_SHIFT; tsens7_point1 = (calib_data[3] & TSENS7_MSM8952_POINT1_MASK); tsens8_point1 = (calib_data[3] & TSENS8_MSM8952_POINT1_MASK) >> TSENS8_MSM8952_POINT1_SHIFT; tsens9_point1 = (calib_data[4] & TSENS9_MSM8952_POINT1_MASK); tsens10_point1 = (calib_data[4] & TSENS10_MSM8952_POINT1_MASK) >> TSENS10_MSM8952_POINT1_SHIFT; } if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { tsens_base1_data = (calib_data[3] & TSENS_MSM8952_BASE1_MASK) >> TSENS_MSM8952_BASE1_SHIFT; tsens0_point2 = (calib_data[0] & TSENS0_MSM8952_POINT2_MASK) >> TSENS0_MSM8952_POINT2_SHIFT; tsens1_point2 = (calib_data[0] & TSENS1_MSM8952_POINT2_MASK) >> TSENS1_MSM8952_POINT2_SHIFT; tsens2_point2 = (calib_data[1] & TSENS2_MSM8952_POINT2_MASK) >> TSENS2_MSM8952_POINT2_SHIFT; tsens3_point2 = (calib_data[1] & TSENS3_MSM8952_POINT2_MASK) >> TSENS3_MSM8952_POINT2_SHIFT; tsens4_point2 = (calib_data[1] & TSENS4_MSM8952_POINT2_MASK) >> TSENS4_MSM8952_POINT2_SHIFT; tsens5_point2 = (calib_data[2] & TSENS5_MSM8952_POINT2_MASK) >> TSENS5_MSM8952_POINT2_SHIFT; tsens6_point2 = (calib_data[2] & TSENS6_MSM8952_POINT2_MASK) >> TSENS6_MSM8952_POINT2_SHIFT; tsens7_point2 = (calib_data[3] & TSENS7_MSM8952_POINT2_MASK) >> TSENS7_MSM8952_POINT2_SHIFT; tsens8_point2 = (calib_data[3] & TSENS8_MSM8952_POINT2_MASK) >> TSENS8_MSM8952_POINT2_SHIFT; tsens9_point2 = (calib_data[4] & TSENS9_MSM8952_POINT2_MASK) >> TSENS9_MSM8952_POINT2_SHIFT; tsens10_point2 = (calib_data[4] & TSENS10_MSM8952_POINT2_MASK) >> TSENS10_MSM8952_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] = 780; calib_tsens_point1_data[i] = 500; } } 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) { 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, temp = 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( TSENS_8939_EEPROM(tmdev->tsens_calib_addr)); calib_data[1] = readl_relaxed( (TSENS_8939_EEPROM(tmdev->tsens_calib_addr) + 0x4)); calib_data[2] = readl_relaxed( (TSENS_8939_EEPROM(tmdev->tsens_calib_addr) + 0x3c)); tsens_calibration_mode = (calib_data[2] & TSENS_MSM8909_TSENS_CAL_SEL) >> TSENS_MSM8909_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[2] & TSENS_MSM8909_BASE0_MASK); tsens0_point1 = (calib_data[0] & TSENS0_MSM8909_POINT1_MASK); tsens1_point1 = (calib_data[0] & TSENS1_MSM8909_POINT1_MASK) >> TSENS1_MSM8909_POINT1_SHIFT; tsens2_point1 = (calib_data[0] & TSENS2_MSM8909_POINT1_MASK) >> TSENS2_MSM8909_POINT1_SHIFT; tsens3_point1 = (calib_data[1] & TSENS3_MSM8909_POINT1_MASK) >> TSENS3_MSM8909_POINT1_SHIFT; tsens4_point1 = (calib_data[1] & TSENS4_MSM8909_POINT1_MASK) >> TSENS4_MSM8909_POINT1_SHIFT; } if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { tsens_base1_data = (calib_data[2] & TSENS_MSM8909_BASE1_MASK) >> TSENS_MSM8909_BASE1_SHIFT; tsens0_point2 = (calib_data[0] & TSENS0_MSM8909_POINT2_MASK) >> TSENS0_MSM8909_POINT2_SHIFT; tsens1_point2 = (calib_data[0] & TSENS1_MSM8909_POINT2_MASK) >> TSENS1_MSM8909_POINT2_SHIFT; tsens2_point2 = (calib_data[0] & TSENS2_MSM8909_POINT2_MASK_0_1) >> TSENS2_MSM8909_POINT2_SHIFT_0_1; temp = (calib_data[1] & TSENS2_MSM8909_POINT2_MASK_2_5) << TSENS2_MSM8909_POINT2_SHIFT_2_5; tsens2_point2 |= temp; tsens3_point2 = (calib_data[1] & TSENS3_MSM8909_POINT2_MASK) >> TSENS3_MSM8909_POINT2_SHIFT; tsens4_point2 = (calib_data[1] & TSENS4_MSM8909_POINT2_MASK) >> TSENS4_MSM8909_POINT2_SHIFT; } if (tsens_calibration_mode == 0) { pr_debug("TSENS is calibrationless mode\n"); for (i = 0; i < tmdev->tsens_num_sensor; i++) calib_tsens_point2_data[i] = 780; calib_tsens_point1_data[0] = 500; calib_tsens_point1_data[1] = 500; calib_tsens_point1_data[2] = 500; calib_tsens_point1_data[3] = 500; calib_tsens_point1_data[4] = 500; } 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[1] = calib_tsens_point1_data[1] - TSENS_MSM8909_D30_WA_S1; 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[3] = calib_tsens_point1_data[3] - TSENS_MSM8909_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_MSM8909_D30_WA_S4; } 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[1] = calib_tsens_point2_data[1] - TSENS_MSM8909_D120_WA_S1; 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[3] = calib_tsens_point2_data[3] - TSENS_MSM8909_D120_WA_S3; calib_tsens_point2_data[4] = ((tsens_base1_data + tsens4_point2) << 2); calib_tsens_point2_data[4] = calib_tsens_point2_data[4] - TSENS_MSM8909_D120_WA_S4; } 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_8939_sensors(void) { int i, tsens_base0_data = 0, tsens_base1_data = 0, v3_enable = 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 tsens_calibration_mode = 0, temp = 0; uint32_t calib_data[6] = {0, 0, 0, 0, 0, 0}; uint32_t calib_tsens_point1_data[10], calib_tsens_point2_data[10]; if (tmdev->tsens_num_sensor == TSENS_NUM_SENSORS_V3) v3_enable = 1; 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)); if (v3_enable) { calib_data[4] = readl_relaxed( (TSENS_8939_EEPROM(tmdev->tsens_calib_addr) - 0x58)); calib_data[5] = readl_relaxed( (TSENS_8939_EEPROM(tmdev->tsens_calib_addr) - 0x54)); } tsens_calibration_mode = (calib_data[0] & TSENS_8939_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_8939_BASE0_MASK); tsens0_point1 = (calib_data[0] & TSENS0_8939_POINT1_MASK) >> TSENS0_8939_POINT1_SHIFT; tsens1_point1 = (calib_data[0] & TSENS1_8939_POINT1_MASK) >> TSENS1_8939_POINT1_SHIFT; tsens2_point1 = (calib_data[0] & TSENS2_8939_POINT1_MASK_0_4) >> TSENS2_8939_POINT1_SHIFT_0_4; temp = (calib_data[1] & TSENS2_8939_POINT1_MASK_5) << TSENS2_8939_POINT1_SHIFT_5; tsens2_point1 |= temp; tsens3_point1 = (calib_data[1] & TSENS3_8939_POINT1_MASK) >> TSENS3_8939_POINT1_SHIFT; tsens4_point1 = (calib_data[1] & TSENS4_8939_POINT1_MASK) >> TSENS4_8939_POINT1_SHIFT; tsens5_point1 = (calib_data[2] & TSENS5_8939_POINT1_MASK) >> TSENS5_8939_POINT1_SHIFT; tsens6_point1 = (calib_data[2] & TSENS6_8939_POINT1_MASK) >> TSENS6_8939_POINT1_SHIFT; tsens7_point1 = (calib_data[3] & TSENS7_8939_POINT1_MASK); tsens8_point1 = (calib_data[3] & TSENS8_8939_POINT1_MASK) >> TSENS8_8939_POINT1_SHIFT; if (v3_enable) tsens9_point1 = (calib_data[4] & TSENS9_8939_POINT1_MASK) >> TSENS9_8939_POINT1_SHIFT; } if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { tsens_base1_data = (calib_data[3] & TSENS_8939_BASE1_MASK) >> TSENS_8939_BASE1_SHIFT; tsens0_point2 = (calib_data[0] & TSENS0_8939_POINT2_MASK) >> TSENS0_8939_POINT2_SHIFT; tsens1_point2 = (calib_data[0] & TSENS1_8939_POINT2_MASK) >> TSENS1_8939_POINT2_SHIFT; tsens2_point2 = (calib_data[1] & TSENS2_8939_POINT2_MASK) >> TSENS2_8939_POINT2_SHIFT; tsens3_point2 = (calib_data[1] & TSENS3_8939_POINT2_MASK) >> TSENS3_8939_POINT2_SHIFT; tsens4_point2 = (calib_data[1] & TSENS4_8939_POINT2_MASK) >> TSENS4_8939_POINT2_SHIFT; tsens5_point2 = (calib_data[2] & TSENS5_8939_POINT2_MASK) >> TSENS5_8939_POINT2_SHIFT; tsens6_point2 = (calib_data[2] & TSENS6_8939_POINT2_MASK) >> TSENS6_8939_POINT2_SHIFT; tsens7_point2 = (calib_data[3] & TSENS7_8939_POINT2_MASK) >> TSENS7_8939_POINT2_SHIFT; tsens8_point2 = (calib_data[3] & TSENS8_8939_POINT2_MASK) >> TSENS8_8939_POINT2_SHIFT; if (v3_enable) { tsens9_point2 = (calib_data[4] & TSENS9_8939_POINT2_MASK_0_4) >> TSENS9_8939_POINT2_SHIFT_0_4; temp = (calib_data[5] & TSENS9_8939_POINT2_MASK_5) >> TSENS9_8939_POINT2_SHIFT_5; tsens9_point2 |= temp; } } if (tsens_calibration_mode == 0) { pr_debug("TSENS is calibrationless mode\n"); for (i = 0; i < tmdev->tsens_num_sensor; i++) { calib_tsens_point2_data[i] = 780; calib_tsens_point1_data[i] = 500; } } 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); 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); if (v3_enable) calib_tsens_point1_data[9] = (((tsens_base0_data) + tsens9_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); 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); if (v3_enable) calib_tsens_point2_data[9] = ((tsens_base1_data + tsens9_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_8916_sensors(void) { 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( TSENS_EEPROM(tmdev->tsens_calib_addr)); calib_data[1] = readl_relaxed( (TSENS_EEPROM(tmdev->tsens_calib_addr) + 0x4)); calib_data[2] = readl_relaxed( (TSENS_EEPROM(tmdev->tsens_calib_addr) + 0x1c)); tsens_calibration_mode = (calib_data[2] & TSENS_8916_TSENS_CAL_SEL) >> TSENS_8916_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_8916_BASE0_MASK); tsens0_point1 = (calib_data[0] & TSENS0_8916_POINT1_MASK) >> TSENS0_8916_POINT1_SHIFT; tsens1_point1 = (calib_data[0] & TSENS1_8916_POINT1_MASK) >> TSENS1_8916_POINT1_SHIFT; tsens2_point1 = (calib_data[0] & TSENS2_8916_POINT1_MASK) >> TSENS2_8916_POINT1_SHIFT; tsens3_point1 = (calib_data[1] & TSENS3_8916_POINT1_MASK) >> TSENS3_8916_POINT1_SHIFT; tsens4_point1 = (calib_data[1] & TSENS4_8916_POINT1_MASK) >> TSENS4_8916_POINT1_SHIFT; } if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { tsens_base1_data = (calib_data[1] & TSENS_8916_BASE1_MASK) >> TSENS_8916_BASE1_SHIFT; tsens0_point2 = (calib_data[0] & TSENS0_8916_POINT2_MASK) >> TSENS0_8916_POINT2_SHIFT; tsens1_point2 = (calib_data[0] & TSENS1_8916_POINT2_MASK) >> TSENS1_8916_POINT2_SHIFT; tsens2_point2 = (calib_data[1] & TSENS2_8916_POINT2_MASK); tsens3_point2 = (calib_data[1] & TSENS3_8916_POINT2_MASK) >> TSENS3_8916_POINT2_SHIFT; tsens4_point2 = (calib_data[1] & TSENS4_8916_POINT2_MASK) >> TSENS4_8916_POINT2_SHIFT; } if (tsens_calibration_mode == 0) { pr_debug("TSENS is calibrationless mode\n"); for (i = 0; i < tmdev->tsens_num_sensor; i++) calib_tsens_point2_data[i] = 780; calib_tsens_point1_data[0] = 500; calib_tsens_point1_data[1] = 500; calib_tsens_point1_data[2] = 500; calib_tsens_point1_data[3] = 500; calib_tsens_point1_data[4] = 500; } 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) << 3); calib_tsens_point1_data[1] = (((tsens_base0_data) + tsens1_point1) << 3); calib_tsens_point1_data[2] = (((tsens_base0_data) + tsens2_point1) << 3); calib_tsens_point1_data[3] = (((tsens_base0_data) + tsens3_point1) << 3); calib_tsens_point1_data[4] = (((tsens_base0_data) + tsens4_point1) << 3); } 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) << 3); calib_tsens_point2_data[1] = ((tsens_base1_data + tsens1_point2) << 3); calib_tsens_point2_data[2] = ((tsens_base1_data + tsens2_point2) << 3); calib_tsens_point2_data[3] = ((tsens_base1_data + tsens3_point2) << 3); calib_tsens_point2_data[4] = ((tsens_base1_data + tsens4_point2) << 3); } 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_9630_sensors(void) { int i, tsens_base0_data = 0, tsens0_point = 0, tsens1_point = 0; int tsens2_point = 0, tsens3_point = 0, tsens4_point = 0; int tsens_base1_data = 0, tsens_calibration_mode = 0, calib_mode = 0; uint32_t calib_data[2], calib_tsens_point_data[5]; if (tmdev->calibration_less_mode) goto calibration_less_mode; calib_data[0] = readl_relaxed( TSENS_EEPROM(tmdev->tsens_calib_addr)); calib_data[1] = readl_relaxed( (TSENS_EEPROM(tmdev->tsens_calib_addr) + 0x4)); calib_mode = (calib_data[1] & TSENS_TORINO_CALIB_PT) >> TSENS_TORINO_CALIB_SHIFT; pr_debug("calib mode is %d\n", calib_mode); if (calib_mode == TSENS_TWO_POINT_CALIB) { tsens_base0_data = (calib_data[0] & TSENS_TORINO_BASE0); tsens_base1_data = (calib_data[0] & TSENS_TORINO_BASE1) >> TSENS_TORINO_BASE1_SHIFT; tsens0_point = (calib_data[0] & TSENS_TORINO_POINT0) >> TSENS_TORINO_POINT0_SHIFT; tsens1_point = (calib_data[0] & TSENS_TORINO_POINT1) >> TSENS_TORINO_POINT1_SHIFT; tsens2_point = (calib_data[0] & TSENS_TORINO_POINT2) >> TSENS_TORINO_POINT2_SHIFT; tsens3_point = (calib_data[0] & TSENS_TORINO_POINT3) >> TSENS_TORINO_POINT3_SHIFT; tsens4_point = (calib_data[0] & TSENS_TORINO_POINT4) >> TSENS_TORINO_POINT4_SHIFT; calib_tsens_point_data[0] = tsens0_point; calib_tsens_point_data[1] = tsens1_point; calib_tsens_point_data[2] = tsens2_point; calib_tsens_point_data[3] = tsens3_point; calib_tsens_point_data[4] = tsens4_point; } if (calib_mode == 0) { calibration_less_mode: pr_debug("TSENS is calibrationless mode\n"); calib_tsens_point_data[0] = 532; calib_tsens_point_data[1] = 532; calib_tsens_point_data[2] = 532; calib_tsens_point_data[3] = 532; calib_tsens_point_data[4] = 532; goto compute_intercept_slope; } 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", 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; } adc_code_of_tempx = tsens_base0_data + calib_tsens_point_data[i]; pr_debug("offset_adc_code_of_tempx:0x%x\n", adc_code_of_tempx); tmdev->sensor[i].offset = (adc_code_of_tempx * 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_8994_sensors(void) { int i, tsens_base0_data = 0, tsens0_point = 0, tsens1_point = 0; int tsens2_point = 0, tsens3_point = 0, tsens4_point = 0; int tsens5_point = 0, tsens6_point = 0, tsens7_point = 0; int tsens8_point = 0, tsens9_point = 0, tsens10_point = 0; int tsens11_point = 0, tsens12_point = 0, tsens13_point = 0; int tsens14_point = 0, tsens15_point = 0; int tsens_base1_data = 0, calib_mode = 0; uint32_t calib_data[6], calib_tsens_point_data[16], calib_redun_sel; if (tmdev->calibration_less_mode) goto calibration_less_mode; calib_redun_sel = readl_relaxed( TSENS_8994_EEPROM_REDUN_SEL(tmdev->tsens_calib_addr)); calib_redun_sel = calib_redun_sel & TSENS_8994_CAL_SEL_REDUN_MASK; calib_redun_sel >>= TSENS_8994_CAL_SEL_REDUN_SHIFT; if (calib_redun_sel == TSENS_QFPROM_BACKUP_SEL) { calib_data[0] = readl_relaxed( TSENS_REDUN_REGION1_EEPROM(tmdev->tsens_calib_addr)); calib_data[1] = readl_relaxed( TSENS_REDUN_REGION2_EEPROM(tmdev->tsens_calib_addr)); calib_data[2] = readl_relaxed( TSENS_REDUN_REGION3_EEPROM(tmdev->tsens_calib_addr)); calib_data[3] = readl_relaxed( TSENS_REDUN_REGION4_EEPROM(tmdev->tsens_calib_addr)); calib_data[4] = readl_relaxed( TSENS_REDUN_REGION5_EEPROM(tmdev->tsens_calib_addr)); calib_mode = (calib_data[4] & TSENS_8994_REDUN_SEL_MASK); pr_debug("calib mode is %d\n", calib_mode); if (calib_mode == TSENS_TWO_POINT_CALIB) { tsens_base0_data = (calib_data[0] & TSENS_BASE0_8994_REDUN_MASK) >> TSENS_BASE0_8994_REDUN_MASK_SHIFT; tsens_base1_data = (calib_data[0] & TSENS_BASE1_BIT0_8994_REDUN_MASK) >> TSENS_BASE1_BIT0_SHIFT_COMPUTE; tsens_base1_data |= (calib_data[1] & TSENS_BASE1_BIT1_9_8994_REDUN_MASK); tsens0_point = (calib_data[1] & TSENS0_OFFSET_8994_REDUN_MASK) >> TSENS0_OFFSET_8994_REDUN_SHIFT; tsens1_point = (calib_data[1] & TSENS1_OFFSET_8994_REDUN_MASK) >> TSENS1_OFFSET_8994_REDUN_SHIFT; tsens2_point = (calib_data[1] & TSENS2_OFFSET_8994_REDUN_MASK) >> TSENS2_OFFSET_8994_REDUN_SHIFT; tsens3_point = (calib_data[1] & TSENS3_OFFSET_8994_REDUN_MASK) >> TSENS3_OFFSET_8994_REDUN_SHIFT; tsens4_point = (calib_data[1] & TSENS4_OFFSET_8994_REDUN_MASK) >> TSENS4_OFFSET_8994_REDUN_SHIFT; tsens5_point = (calib_data[1] & TSENS5_OFFSET_8994_REDUN_MASK_BIT0_2) >> TSENS5_OFFSET_8994_REDUN_SHIFT_BIT0_2; tsens5_point |= ((calib_data[2] & TSENS5_OFFSET_8994_REDUN_MASK_BIT3) >> TSENS5_OFFSET_8994_REDUN_SHIFT_BIT3); tsens6_point = (calib_data[2] & TSENS6_OFFSET_8994_REDUN_MASK) >> TSENS6_OFFSET_8994_REDUN_SHIFT; tsens7_point = (calib_data[2] & TSENS7_OFFSET_8994_REDUN_MASK) >> TSENS7_OFFSET_8994_REDUN_SHIFT; tsens8_point = (calib_data[3] & TSENS8_OFFSET_8994_REDUN_MASK); tsens9_point = (calib_data[3] & TSENS9_OFFSET_8994_REDUN_MASK) >> TSENS9_OFFSET_8994_REDUN_SHIFT; tsens10_point = (calib_data[3] & TSENS10_OFFSET_8994_REDUN_MASK) >> TSENS10_OFFSET_8994_REDUN_SHIFT; tsens11_point = (calib_data[3] & TSENS11_OFFSET_8994_REDUN_MASK) >> TSENS11_OFFSET_8994_REDUN_SHIFT; tsens12_point = (calib_data[3] & TSENS12_OFFSET_8994_REDUN_MASK) >> TSENS12_OFFSET_8994_REDUN_SHIFT; tsens13_point = (calib_data[3] & TSENS13_OFFSET_8994_REDUN_MASK) >> TSENS13_OFFSET_8994_REDUN_SHIFT; tsens14_point = (calib_data[3] & TSENS14_OFFSET_8994_REDUN_MASK) >> TSENS14_OFFSET_8994_REDUN_SHIFT; tsens15_point = (calib_data[3] & TSENS15_OFFSET_8994_REDUN_MASK) >> TSENS15_OFFSET_8994_REDUN_SHIFT; calib_tsens_point_data[0] = tsens0_point; calib_tsens_point_data[1] = tsens1_point; calib_tsens_point_data[2] = tsens2_point; calib_tsens_point_data[3] = tsens3_point; calib_tsens_point_data[4] = tsens4_point; calib_tsens_point_data[5] = tsens5_point; calib_tsens_point_data[6] = tsens6_point; calib_tsens_point_data[7] = tsens7_point; calib_tsens_point_data[8] = tsens8_point; calib_tsens_point_data[9] = tsens9_point; calib_tsens_point_data[10] = tsens10_point; calib_tsens_point_data[11] = tsens11_point; calib_tsens_point_data[12] = tsens12_point; calib_tsens_point_data[13] = tsens13_point; calib_tsens_point_data[14] = tsens14_point; calib_tsens_point_data[15] = tsens15_point; } else goto calibration_less_mode; } else { calib_data[0] = readl_relaxed( TSENS_8994_EEPROM(tmdev->tsens_calib_addr)); calib_data[1] = readl_relaxed( (TSENS_8994_EEPROM(tmdev->tsens_calib_addr) + 0x4)); calib_data[2] = readl_relaxed( (TSENS_8994_EEPROM(tmdev->tsens_calib_addr) + 0x8)); calib_mode = (calib_data[2] & TSENS_8994_CAL_SEL_MASK) >> TSENS_8994_CAL_SEL_SHIFT; pr_debug("calib mode is %d\n", calib_mode); if (calib_mode == TSENS_TWO_POINT_CALIB) { tsens_base0_data = (calib_data[0] & TSENS_BASE0_8994_MASK); tsens_base1_data = (calib_data[0] & TSENS_BASE1_8994_MASK) >> TSENS_BASE1_8994_SHIFT; tsens0_point = (calib_data[0] & TSENS0_OFFSET_8994_MASK) >> TSENS0_OFFSET_8994_SHIFT; tsens1_point = (calib_data[0] & TSENS1_OFFSET_8994_MASK) >> TSENS1_OFFSET_8994_SHIFT; tsens2_point = (calib_data[0] & TSENS2_OFFSET_8994_MASK) >> TSENS2_OFFSET_8994_SHIFT; tsens3_point = (calib_data[1] & TSENS3_OFFSET_8994_MASK); tsens4_point = (calib_data[1] & TSENS4_OFFSET_8994_MASK) >> TSENS4_OFFSET_8994_SHIFT; tsens5_point = (calib_data[1] & TSENS5_OFFSET_8994_MASK) >> TSENS5_OFFSET_8994_SHIFT; tsens6_point = (calib_data[1] & TSENS6_OFFSET_8994_MASK) >> TSENS6_OFFSET_8994_SHIFT; tsens7_point = (calib_data[1] & TSENS7_OFFSET_8994_MASK) >> TSENS7_OFFSET_8994_SHIFT; tsens8_point = (calib_data[1] & TSENS8_OFFSET_8994_MASK) >> TSENS8_OFFSET_8994_SHIFT; tsens9_point = (calib_data[1] & TSENS9_OFFSET_8994_MASK) >> TSENS9_OFFSET_8994_SHIFT; tsens10_point = (calib_data[1] & TSENS10_OFFSET_8994_MASK) >> TSENS10_OFFSET_8994_SHIFT; tsens11_point = (calib_data[2] & TSENS11_OFFSET_8994_MASK); tsens12_point = (calib_data[2] & TSENS12_OFFSET_8994_MASK) >> TSENS12_OFFSET_8994_SHIFT; tsens13_point = (calib_data[2] & TSENS13_OFFSET_8994_MASK) >> TSENS13_OFFSET_8994_SHIFT; tsens14_point = (calib_data[2] & TSENS14_OFFSET_8994_MASK) >> TSENS14_OFFSET_8994_SHIFT; tsens15_point = (calib_data[2] & TSENS15_OFFSET_8994_MASK) >> TSENS15_OFFSET_8994_SHIFT; calib_tsens_point_data[0] = tsens0_point; calib_tsens_point_data[1] = tsens1_point; calib_tsens_point_data[2] = tsens2_point; calib_tsens_point_data[3] = tsens3_point; calib_tsens_point_data[4] = tsens4_point; calib_tsens_point_data[5] = tsens5_point; calib_tsens_point_data[6] = tsens6_point; calib_tsens_point_data[7] = tsens7_point; calib_tsens_point_data[8] = tsens8_point; calib_tsens_point_data[9] = tsens9_point; calib_tsens_point_data[10] = tsens10_point; calib_tsens_point_data[11] = tsens11_point; calib_tsens_point_data[12] = tsens12_point; calib_tsens_point_data[13] = tsens13_point; calib_tsens_point_data[14] = tsens14_point; calib_tsens_point_data[15] = tsens15_point; } else { calibration_less_mode: pr_debug("TSENS is calibrationless mode\n"); calib_tsens_point_data[0] = 532; calib_tsens_point_data[1] = 532; calib_tsens_point_data[2] = 532; calib_tsens_point_data[3] = 532; calib_tsens_point_data[4] = 532; calib_tsens_point_data[5] = 532; calib_tsens_point_data[6] = 532; calib_tsens_point_data[7] = 532; calib_tsens_point_data[8] = 532; calib_tsens_point_data[9] = 532; calib_tsens_point_data[10] = 532; calib_tsens_point_data[11] = 532; calib_tsens_point_data[12] = 532; calib_tsens_point_data[13] = 532; calib_tsens_point_data[14] = 532; calib_tsens_point_data[15] = 532; } } 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", i, tmdev->sensor[i].calib_data_point1, tmdev->sensor[i].calib_data_point2); if (calib_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; } adc_code_of_tempx = tsens_base0_data + calib_tsens_point_data[i]; pr_debug("offset_adc_code_of_tempx:0x%x\n", adc_code_of_tempx); tmdev->sensor[i].offset = (adc_code_of_tempx * 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_8992_sensors(void) { int i, tsens_base0_data = 0, tsens0_point = 0, tsens1_point = 0; int tsens2_point = 0, tsens3_point = 0, tsens4_point = 0; int tsens5_point = 0, tsens6_point = 0, tsens7_point = 0; int tsens8_point = 0, tsens9_point = 0, tsens10_point = 0; int tsens11_point = 0, tsens12_point = 0, tsens13_point = 0; int tsens14_point = 0, tsens15_point = 0; int tsens_base1_data = 0, calib_mode = 0; uint32_t calib_data[6], calib_tsens_point_data[16], calib_redun_sel; if (tmdev->calibration_less_mode) goto calibration_less_mode; calib_redun_sel = readl_relaxed( TSENS_8994_EEPROM_REDUN_SEL(tmdev->tsens_calib_addr)); calib_redun_sel = calib_redun_sel & TSENS_8994_CAL_SEL_REDUN_MASK; calib_redun_sel >>= TSENS_8994_CAL_SEL_REDUN_SHIFT; if (calib_redun_sel == TSENS_QFPROM_BACKUP_SEL) { calib_data[0] = readl_relaxed( TSENS_REDUN_REGION1_EEPROM(tmdev->tsens_calib_addr)); calib_data[1] = readl_relaxed( TSENS_REDUN_REGION2_EEPROM(tmdev->tsens_calib_addr)); calib_data[2] = readl_relaxed( TSENS_REDUN_REGION3_EEPROM(tmdev->tsens_calib_addr)); calib_data[3] = readl_relaxed( TSENS_REDUN_REGION4_EEPROM(tmdev->tsens_calib_addr)); calib_data[4] = readl_relaxed( TSENS_REDUN_REGION5_EEPROM(tmdev->tsens_calib_addr)); calib_mode = (calib_data[4] & TSENS_8994_REDUN_SEL_MASK); pr_debug("calib mode is %d\n", calib_mode); if (calib_mode == TSENS_TWO_POINT_CALIB) { tsens_base0_data = (calib_data[0] & TSENS_BASE0_8994_REDUN_MASK) >> TSENS_BASE0_8994_REDUN_MASK_SHIFT; tsens_base1_data = (calib_data[0] & TSENS_BASE1_BIT0_8994_REDUN_MASK) >> TSENS_BASE1_BIT0_SHIFT_COMPUTE; tsens_base1_data |= (calib_data[1] & TSENS_BASE1_BIT1_9_8994_REDUN_MASK); tsens0_point = (calib_data[1] & TSENS0_OFFSET_8994_REDUN_MASK) >> TSENS0_OFFSET_8994_REDUN_SHIFT; tsens1_point = (calib_data[1] & TSENS1_OFFSET_8994_REDUN_MASK) >> TSENS1_OFFSET_8994_REDUN_SHIFT; tsens2_point = (calib_data[1] & TSENS2_OFFSET_8994_REDUN_MASK) >> TSENS2_OFFSET_8994_REDUN_SHIFT; tsens3_point = (calib_data[1] & TSENS3_OFFSET_8994_REDUN_MASK) >> TSENS3_OFFSET_8994_REDUN_SHIFT; tsens4_point = (calib_data[1] & TSENS4_OFFSET_8994_REDUN_MASK) >> TSENS4_OFFSET_8994_REDUN_SHIFT; tsens5_point = (calib_data[1] & TSENS5_OFFSET_8994_REDUN_MASK_BIT0_2) >> TSENS5_OFFSET_8994_REDUN_SHIFT_BIT0_2; tsens5_point |= ((calib_data[2] & TSENS5_OFFSET_8994_REDUN_MASK_BIT3) >> TSENS5_OFFSET_8994_REDUN_SHIFT_BIT3); tsens6_point = (calib_data[2] & TSENS6_OFFSET_8994_REDUN_MASK) >> TSENS6_OFFSET_8994_REDUN_SHIFT; tsens7_point = (calib_data[2] & TSENS7_OFFSET_8994_REDUN_MASK) >> TSENS7_OFFSET_8994_REDUN_SHIFT; tsens8_point = (calib_data[3] & TSENS8_OFFSET_8994_REDUN_MASK); tsens9_point = (calib_data[3] & TSENS9_OFFSET_8994_REDUN_MASK) >> TSENS9_OFFSET_8994_REDUN_SHIFT; tsens10_point = (calib_data[3] & TSENS10_OFFSET_8994_REDUN_MASK) >> TSENS10_OFFSET_8994_REDUN_SHIFT; tsens11_point = (calib_data[3] & TSENS11_OFFSET_8994_REDUN_MASK) >> TSENS11_OFFSET_8994_REDUN_SHIFT; tsens12_point = (calib_data[3] & TSENS12_OFFSET_8994_REDUN_MASK) >> TSENS12_OFFSET_8994_REDUN_SHIFT; tsens13_point = (calib_data[3] & TSENS13_OFFSET_8994_REDUN_MASK) >> TSENS13_OFFSET_8994_REDUN_SHIFT; tsens14_point = (calib_data[3] & TSENS14_OFFSET_8994_REDUN_MASK) >> TSENS14_OFFSET_8994_REDUN_SHIFT; tsens15_point = (calib_data[3] & TSENS15_OFFSET_8994_REDUN_MASK) >> TSENS15_OFFSET_8994_REDUN_SHIFT; calib_tsens_point_data[0] = tsens0_point; calib_tsens_point_data[1] = tsens1_point; calib_tsens_point_data[2] = tsens2_point; calib_tsens_point_data[3] = tsens3_point; calib_tsens_point_data[4] = tsens4_point; calib_tsens_point_data[5] = tsens5_point; calib_tsens_point_data[6] = tsens7_point; calib_tsens_point_data[7] = tsens9_point; calib_tsens_point_data[8] = tsens10_point; calib_tsens_point_data[9] = tsens11_point; calib_tsens_point_data[10] = tsens12_point; calib_tsens_point_data[11] = tsens13_point; calib_tsens_point_data[12] = tsens14_point; } else goto calibration_less_mode; } else { calib_data[0] = readl_relaxed( TSENS_8994_EEPROM(tmdev->tsens_calib_addr)); calib_data[1] = readl_relaxed( (TSENS_8994_EEPROM(tmdev->tsens_calib_addr) + 0x4)); calib_data[2] = readl_relaxed( (TSENS_8994_EEPROM(tmdev->tsens_calib_addr) + 0x8)); calib_mode = (calib_data[2] & TSENS_8994_CAL_SEL_MASK) >> TSENS_8994_CAL_SEL_SHIFT; pr_debug("calib mode is %d\n", calib_mode); if (calib_mode == TSENS_TWO_POINT_CALIB) { tsens_base0_data = (calib_data[0] & TSENS_BASE0_8994_MASK); tsens_base1_data = (calib_data[0] & TSENS_BASE1_8994_MASK) >> TSENS_BASE1_8994_SHIFT; tsens0_point = (calib_data[0] & TSENS0_OFFSET_8994_MASK) >> TSENS0_OFFSET_8994_SHIFT; tsens1_point = (calib_data[0] & TSENS1_OFFSET_8994_MASK) >> TSENS1_OFFSET_8994_SHIFT; tsens2_point = (calib_data[0] & TSENS2_OFFSET_8994_MASK) >> TSENS2_OFFSET_8994_SHIFT; tsens3_point = (calib_data[1] & TSENS3_OFFSET_8994_MASK); tsens4_point = (calib_data[1] & TSENS4_OFFSET_8994_MASK) >> TSENS4_OFFSET_8994_SHIFT; tsens5_point = (calib_data[1] & TSENS5_OFFSET_8994_MASK) >> TSENS5_OFFSET_8994_SHIFT; tsens7_point = (calib_data[1] & TSENS6_OFFSET_8994_MASK) >> TSENS6_OFFSET_8994_SHIFT; tsens9_point = (calib_data[1] & TSENS7_OFFSET_8994_MASK) >> TSENS7_OFFSET_8994_SHIFT; tsens10_point = (calib_data[1] & TSENS8_OFFSET_8994_MASK) >> TSENS8_OFFSET_8994_SHIFT; tsens11_point = (calib_data[1] & TSENS9_OFFSET_8994_MASK) >> TSENS9_OFFSET_8994_SHIFT; tsens12_point = (calib_data[1] & TSENS10_OFFSET_8994_MASK) >> TSENS10_OFFSET_8994_SHIFT; tsens13_point = (calib_data[2] & TSENS11_OFFSET_8994_MASK); tsens14_point = (calib_data[2] & TSENS12_OFFSET_8994_MASK) >> TSENS12_OFFSET_8994_SHIFT; calib_tsens_point_data[0] = tsens0_point; calib_tsens_point_data[1] = tsens1_point; calib_tsens_point_data[2] = tsens2_point; calib_tsens_point_data[3] = tsens3_point; calib_tsens_point_data[4] = tsens4_point; calib_tsens_point_data[5] = tsens5_point; calib_tsens_point_data[6] = tsens7_point; calib_tsens_point_data[7] = tsens9_point; calib_tsens_point_data[8] = tsens10_point; calib_tsens_point_data[9] = tsens11_point; calib_tsens_point_data[10] = tsens12_point; calib_tsens_point_data[11] = tsens13_point; calib_tsens_point_data[12] = tsens14_point; } else { calibration_less_mode: pr_debug("TSENS is calibrationless mode\n"); calib_tsens_point_data[0] = 532; calib_tsens_point_data[1] = 532; calib_tsens_point_data[2] = 532; calib_tsens_point_data[3] = 532; calib_tsens_point_data[4] = 532; calib_tsens_point_data[5] = 532; calib_tsens_point_data[6] = 532; calib_tsens_point_data[7] = 532; calib_tsens_point_data[8] = 532; calib_tsens_point_data[9] = 532; calib_tsens_point_data[10] = 532; calib_tsens_point_data[11] = 532; calib_tsens_point_data[12] = 532; calib_tsens_point_data[13] = 532; calib_tsens_point_data[14] = 532; calib_tsens_point_data[15] = 532; } } 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", i, tmdev->sensor[i].calib_data_point1, tmdev->sensor[i].calib_data_point2); if (calib_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; } adc_code_of_tempx = tsens_base0_data + calib_tsens_point_data[i]; pr_debug("offset_adc_code_of_tempx:0x%x\n", adc_code_of_tempx); tmdev->sensor[i].offset = (adc_code_of_tempx * 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_8x10_sensors(void) { int i, tsens_base0_data = 0, tsens0_point1 = 0, tsens1_point1 = 0; int tsens0_point2 = 0, tsens1_point2 = 0; int tsens_base1_data = 0, tsens_calibration_mode = 0; uint32_t calib_data[2], calib_redun_sel; uint32_t calib_tsens_point1_data[2], calib_tsens_point2_data[2]; if (tmdev->calibration_less_mode) goto calibration_less_mode; calib_redun_sel = readl_relaxed( TSENS_EEPROM_8X10_2(tmdev->tsens_calib_addr)); calib_redun_sel = calib_redun_sel & TSENS_8X10_REDUN_SEL_MASK; calib_redun_sel >>= TSENS_8X10_REDUN_SEL_SHIFT; pr_debug("calib_redun_sel:%x\n", calib_redun_sel); if (calib_redun_sel == TSENS_QFPROM_BACKUP_SEL) { calib_data[0] = readl_relaxed( TSENS_EEPROM_8X10_SPARE_1(tmdev->tsens_calib_addr)); calib_data[1] = readl_relaxed( TSENS_EEPROM_8X10_SPARE_2(tmdev->tsens_calib_addr)); } else { calib_data[0] = readl_relaxed( TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr)); calib_data[1] = readl_relaxed( (TSENS_EEPROM_8X10_1(tmdev->tsens_calib_addr) + TSENS_EEPROM_8X10_1_OFFSET)); } tsens_calibration_mode = (calib_data[0] & TSENS_8X10_TSENS_CAL_SEL) >> TSENS_8X10_CAL_SEL_SHIFT; pr_debug("calib mode scheme:%x\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_8X10_BASE0_MASK); tsens0_point1 = (calib_data[0] & TSENS0_8X10_POINT1_MASK) >> TSENS0_8X10_POINT1_SHIFT; tsens1_point1 = calib_data[1] & TSENS1_8X10_POINT1_MASK; } else goto calibration_less_mode; if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { tsens_base1_data = (calib_data[0] & TSENS_8X10_BASE1_MASK) >> TSENS_8X10_BASE1_SHIFT; tsens0_point2 = (calib_data[0] & TSENS0_8X10_POINT2_MASK) >> TSENS0_8X10_POINT2_SHIFT; tsens1_point2 = (calib_data[1] & TSENS1_8X10_POINT2_MASK) >> TSENS1_8X10_POINT2_SHIFT; } if (tsens_calibration_mode == 0) { calibration_less_mode: pr_debug("TSENS is calibrationless mode\n"); for (i = 0; i < tmdev->tsens_num_sensor; i++) calib_tsens_point2_data[i] = 780; calib_tsens_point1_data[0] = 595; calib_tsens_point1_data[1] = 629; goto compute_intercept_slope; } 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) | TSENS_BIT_APPEND); calib_tsens_point1_data[1] = ((((tsens_base0_data) + tsens1_point1) << 2) | TSENS_BIT_APPEND); } 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) | TSENS_BIT_APPEND); calib_tsens_point2_data[1] = (((tsens_base1_data + tsens1_point2) << 2) | TSENS_BIT_APPEND); } 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", 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); tmdev->prev_reading_avail = false; } return 0; } static int tsens_calib_8x26_sensors(void) { int i, tsens_base0_data = 0, tsens0_point1 = 0, tsens1_point1 = 0; int tsens2_point1 = 0, tsens3_point1 = 0, tsens4_point1 = 0; int tsens5_point1 = 0, tsens6_point1 = 0, tsens6_point2 = 0; int tsens0_point2 = 0, tsens1_point2 = 0, tsens2_point2 = 0; int tsens3_point2 = 0, tsens4_point2 = 0, tsens5_point2 = 0; int tsens_base1_data = 0, tsens_calibration_mode = 0; uint32_t calib_data[6]; uint32_t calib_tsens_point1_data[7], calib_tsens_point2_data[7]; if (tmdev->calibration_less_mode) goto calibration_less_mode; for (i = 0; i < TSENS_8X26_MAIN_CALIB_ADDR_RANGE; i++) calib_data[i] = readl_relaxed( (TSENS_EEPROM_8X26_1(tmdev->tsens_calib_addr)) + (i * TSENS_SN_ADDR_OFFSET)); calib_data[4] = readl_relaxed( (TSENS_EEPROM_8X26_2(tmdev->tsens_calib_addr))); calib_data[5] = readl_relaxed( (TSENS_EEPROM_8X26_2(tmdev->tsens_calib_addr)) + 0x8); tsens_calibration_mode = (calib_data[5] & TSENS_8X26_TSENS_CAL_SEL) >> TSENS_8X26_CAL_SEL_SHIFT; pr_debug("calib mode scheme:%x\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_8X26_BASE0_MASK) >> TSENS_8X26_BASE0_SHIFT; tsens0_point1 = (calib_data[0] & TSENS0_8X26_POINT1_MASK) >> TSENS0_8X26_POINT1_SHIFT; tsens1_point1 = calib_data[1] & TSENS1_8X26_POINT1_MASK; tsens2_point1 = (calib_data[1] & TSENS2_8X26_POINT1_MASK) >> TSENS2_8X26_POINT1_SHIFT; tsens3_point1 = (calib_data[1] & TSENS3_8X26_POINT1_MASK) >> TSENS3_8X26_POINT1_SHIFT; tsens4_point1 = (calib_data[1] & TSENS4_8X26_POINT1_MASK) >> TSENS4_8X26_POINT1_SHIFT; tsens5_point1 = (calib_data[1] & TSENS5_8X26_POINT1_MASK) >> TSENS5_8X26_POINT1_SHIFT; tsens6_point1 = (calib_data[2] & TSENS6_8X26_POINT1_MASK) >> TSENS6_8X26_POINT1_SHIFT; } else goto calibration_less_mode; if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { tsens_base1_data = (calib_data[3] & TSENS_8X26_BASE1_MASK); tsens0_point2 = (calib_data[3] & TSENS0_8X26_POINT2_MASK) >> TSENS0_8X26_POINT2_SHIFT; tsens1_point2 = (calib_data[3] & TSENS1_8X26_POINT2_MASK) >> TSENS1_8X26_POINT2_SHIFT; tsens2_point2 = (calib_data[3] & TSENS2_8X26_POINT2_MASK) >> TSENS2_8X26_POINT2_SHIFT; tsens3_point2 = (calib_data[3] & TSENS3_8X26_POINT2_MASK) >> TSENS3_8X26_POINT2_SHIFT; tsens4_point2 = (calib_data[4] & TSENS4_8X26_POINT2_MASK) >> TSENS4_8X26_POINT2_SHIFT; tsens5_point2 = (calib_data[4] & TSENS5_8X26_POINT2_MASK) >> TSENS5_8X26_POINT2_SHIFT; tsens6_point2 = (calib_data[5] & TSENS6_8X26_POINT2_MASK) >> TSENS6_8X26_POINT2_SHIFT; } if (tsens_calibration_mode == 0) { calibration_less_mode: pr_debug("TSENS is calibrationless mode\n"); for (i = 0; i < tmdev->tsens_num_sensor; i++) calib_tsens_point2_data[i] = 780; calib_tsens_point1_data[0] = 595; calib_tsens_point1_data[1] = 625; calib_tsens_point1_data[2] = 553; calib_tsens_point1_data[3] = 578; calib_tsens_point1_data[4] = 505; calib_tsens_point1_data[5] = 509; calib_tsens_point1_data[6] = 507; goto compute_intercept_slope; } 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) | TSENS_BIT_APPEND); calib_tsens_point1_data[1] = ((((tsens_base0_data) + tsens1_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[2] = ((((tsens_base0_data) + tsens2_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[3] = ((((tsens_base0_data) + tsens3_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[4] = ((((tsens_base0_data) + tsens4_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[5] = ((((tsens_base0_data) + tsens5_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[6] = ((((tsens_base0_data) + tsens6_point1) << 2) | TSENS_BIT_APPEND); } 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) | TSENS_BIT_APPEND); calib_tsens_point2_data[1] = (((tsens_base1_data + tsens1_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[2] = (((tsens_base1_data + tsens2_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[3] = (((tsens_base1_data + tsens3_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[4] = (((tsens_base1_data + tsens4_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[5] = (((tsens_base1_data + tsens5_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[6] = (((tsens_base1_data + tsens6_point2) << 2) | TSENS_BIT_APPEND); } 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", 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); tmdev->prev_reading_avail = false; } return 0; } static int tsens_calib_8974_sensors(void) { int i, tsens_base1_data = 0, tsens0_point1 = 0, tsens1_point1 = 0; int tsens2_point1 = 0, tsens3_point1 = 0, tsens4_point1 = 0; int tsens5_point1 = 0, tsens6_point1 = 0, tsens7_point1 = 0; int tsens8_point1 = 0, tsens9_point1 = 0, tsens10_point1 = 0; int tsens0_point2 = 0, tsens1_point2 = 0, tsens2_point2 = 0; int tsens3_point2 = 0, tsens4_point2 = 0, tsens5_point2 = 0; int tsens6_point2 = 0, tsens7_point2 = 0, tsens8_point2 = 0; int tsens9_point2 = 0, tsens10_point2 = 0; int tsens_base2_data = 0, tsens_calibration_mode = 0, temp = 0; uint32_t calib_data[6], calib_redun_sel, calib_data_backup[4]; uint32_t calib_tsens_point1_data[11], calib_tsens_point2_data[11]; if (tmdev->calibration_less_mode) goto calibration_less_mode; calib_redun_sel = readl_relaxed( TSENS_EEPROM_REDUNDANCY_SEL(tmdev->tsens_calib_addr)); calib_redun_sel = calib_redun_sel & TSENS_QFPROM_BACKUP_REDUN_SEL; calib_redun_sel >>= TSENS_QFPROM_BACKUP_REDUN_SHIFT; pr_debug("calib_redun_sel:%x\n", calib_redun_sel); for (i = 0; i < TSENS_MAIN_CALIB_ADDR_RANGE; i++) { calib_data[i] = readl_relaxed( (TSENS_EEPROM(tmdev->tsens_calib_addr)) + (i * TSENS_SN_ADDR_OFFSET)); pr_debug("calib raw data row%d:0x%x\n", i, calib_data[i]); } if (calib_redun_sel == TSENS_QFPROM_BACKUP_SEL) { tsens_calibration_mode = (calib_data[4] & TSENS_CAL_SEL_0_1) >> TSENS_CAL_SEL_SHIFT; temp = (calib_data[5] & TSENS_CAL_SEL_2) >> TSENS_CAL_SEL_SHIFT_2; tsens_calibration_mode |= temp; pr_debug("backup calib mode:%x\n", calib_redun_sel); for (i = 0; i < TSENS_BACKUP_CALIB_ADDR_RANGE; i++) calib_data_backup[i] = readl_relaxed( (TSENS_EEPROM_BACKUP_REGION( tmdev->tsens_calib_addr)) + (i * TSENS_SN_ADDR_OFFSET)); if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB) || (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) || (tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) { tsens_base1_data = (calib_data_backup[0] & TSENS_BASE1_MASK); tsens0_point1 = (calib_data_backup[0] & TSENS0_POINT1_MASK) >> TSENS0_POINT1_SHIFT; tsens1_point1 = (calib_data_backup[0] & TSENS1_POINT1_MASK) >> TSENS1_POINT1_SHIFT; tsens2_point1 = (calib_data_backup[0] & TSENS2_POINT1_MASK) >> TSENS2_POINT1_SHIFT; tsens3_point1 = (calib_data_backup[0] & TSENS3_POINT1_MASK) >> TSENS3_POINT1_SHIFT; tsens4_point1 = (calib_data_backup[1] & TSENS4_POINT1_MASK); tsens5_point1 = (calib_data_backup[1] & TSENS5_POINT1_MASK) >> TSENS5_POINT1_SHIFT; tsens6_point1 = (calib_data_backup[1] & TSENS6_POINT1_MASK) >> TSENS6_POINT1_SHIFT; tsens7_point1 = (calib_data_backup[1] & TSENS7_POINT1_MASK) >> TSENS7_POINT1_SHIFT; tsens8_point1 = (calib_data_backup[2] & TSENS8_POINT1_MASK_BACKUP) >> TSENS8_POINT1_SHIFT; tsens9_point1 = (calib_data_backup[2] & TSENS9_POINT1_MASK_BACKUP) >> TSENS9_POINT1_BACKUP_SHIFT; tsens10_point1 = (calib_data_backup[2] & TSENS10_POINT1_MASK_BACKUP) >> TSENS10_POINT1_BACKUP_SHIFT; } else goto calibration_less_mode; if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { tsens_base2_data = (calib_data_backup[2] & TSENS_BASE2_BACKUP_MASK) >> TSENS_POINT2_BASE_BACKUP_SHIFT; tsens0_point2 = (calib_data_backup[2] & TSENS0_POINT2_BACKUP_MASK) >> TSENS0_POINT2_BACKUP_SHIFT; tsens1_point2 = (calib_data_backup[3] & TSENS1_POINT2_BACKUP_MASK); tsens2_point2 = (calib_data_backup[3] & TSENS2_POINT2_BACKUP_MASK) >> TSENS2_POINT2_BACKUP_SHIFT; tsens3_point2 = (calib_data_backup[3] & TSENS3_POINT2_BACKUP_MASK) >> TSENS3_POINT2_BACKUP_SHIFT; tsens4_point2 = (calib_data_backup[3] & TSENS4_POINT2_BACKUP_MASK) >> TSENS4_POINT2_BACKUP_SHIFT; tsens5_point2 = (calib_data[4] & TSENS5_POINT2_BACKUP_MASK) >> TSENS5_POINT2_BACKUP_SHIFT; tsens6_point2 = (calib_data[5] & TSENS6_POINT2_BACKUP_MASK); tsens7_point2 = (calib_data[5] & TSENS7_POINT2_BACKUP_MASK) >> TSENS7_POINT2_BACKUP_SHIFT; tsens8_point2 = (calib_data[5] & TSENS8_POINT2_BACKUP_MASK) >> TSENS8_POINT2_BACKUP_SHIFT; tsens9_point2 = (calib_data[5] & TSENS9_POINT2_BACKUP_MASK) >> TSENS9_POINT2_BACKUP_SHIFT; tsens10_point2 = (calib_data[5] & TSENS10_POINT2_BACKUP_MASK) >> TSENS10_POINT2_BACKUP_SHIFT; } } else { tsens_calibration_mode = (calib_data[1] & TSENS_CAL_SEL_0_1) >> TSENS_CAL_SEL_SHIFT; temp = (calib_data[3] & TSENS_CAL_SEL_2) >> TSENS_CAL_SEL_SHIFT_2; tsens_calibration_mode |= temp; pr_debug("calib mode scheme:%x\n", tsens_calibration_mode); if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB) || (tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) || (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) { tsens_base1_data = (calib_data[0] & TSENS_BASE1_MASK); tsens0_point1 = (calib_data[0] & TSENS0_POINT1_MASK) >> TSENS0_POINT1_SHIFT; tsens1_point1 = (calib_data[0] & TSENS1_POINT1_MASK) >> TSENS1_POINT1_SHIFT; tsens2_point1 = (calib_data[0] & TSENS2_POINT1_MASK) >> TSENS2_POINT1_SHIFT; tsens3_point1 = (calib_data[0] & TSENS3_POINT1_MASK) >> TSENS3_POINT1_SHIFT; tsens4_point1 = (calib_data[1] & TSENS4_POINT1_MASK); tsens5_point1 = (calib_data[1] & TSENS5_POINT1_MASK) >> TSENS5_POINT1_SHIFT; tsens6_point1 = (calib_data[1] & TSENS6_POINT1_MASK) >> TSENS6_POINT1_SHIFT; tsens7_point1 = (calib_data[1] & TSENS7_POINT1_MASK) >> TSENS7_POINT1_SHIFT; tsens8_point1 = (calib_data[1] & TSENS8_POINT1_MASK) >> TSENS8_POINT1_SHIFT; tsens9_point1 = (calib_data[2] & TSENS9_POINT1_MASK); tsens10_point1 = (calib_data[2] & TSENS10_POINT1_MASK) >> TSENS10_POINT1_SHIFT; } else goto calibration_less_mode; if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { tsens_base2_data = (calib_data[2] & TSENS_BASE2_MASK) >> TSENS_POINT2_BASE_SHIFT; tsens0_point2 = (calib_data[2] & TSENS0_POINT2_MASK) >> TSENS0_POINT2_SHIFT; tsens1_point2 = (calib_data[2] & TSENS1_POINT2_MASK) >> TSENS1_POINT2_SHIFT; tsens2_point2 = (calib_data[3] & TSENS2_POINT2_MASK); tsens3_point2 = (calib_data[3] & TSENS3_POINT2_MASK) >> TSENS3_POINT2_SHIFT; tsens4_point2 = (calib_data[3] & TSENS4_POINT2_MASK) >> TSENS4_POINT2_SHIFT; tsens5_point2 = (calib_data[3] & TSENS5_POINT2_MASK) >> TSENS5_POINT2_SHIFT; tsens6_point2 = (calib_data[3] & TSENS6_POINT2_MASK) >> TSENS6_POINT2_SHIFT; tsens7_point2 = (calib_data[4] & TSENS7_POINT2_MASK); tsens8_point2 = (calib_data[4] & TSENS8_POINT2_MASK) >> TSENS8_POINT2_SHIFT; tsens9_point2 = (calib_data[4] & TSENS9_POINT2_MASK) >> TSENS9_POINT2_SHIFT; tsens10_point2 = (calib_data[4] & TSENS10_POINT2_MASK) >> TSENS10_POINT2_SHIFT; } if (tsens_calibration_mode == 0) { calibration_less_mode: pr_debug("TSENS is calibrationless mode\n"); for (i = 0; i < tmdev->tsens_num_sensor; i++) calib_tsens_point2_data[i] = 780; calib_tsens_point1_data[0] = 502; calib_tsens_point1_data[1] = 509; calib_tsens_point1_data[2] = 503; calib_tsens_point1_data[3] = 509; calib_tsens_point1_data[4] = 505; calib_tsens_point1_data[5] = 509; calib_tsens_point1_data[6] = 507; calib_tsens_point1_data[7] = 510; calib_tsens_point1_data[8] = 508; calib_tsens_point1_data[9] = 509; calib_tsens_point1_data[10] = 508; goto compute_intercept_slope; } } if (tsens_calibration_mode == TSENS_ONE_POINT_CALIB) { calib_tsens_point1_data[0] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens0_point1; calib_tsens_point1_data[1] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens1_point1; calib_tsens_point1_data[2] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens2_point1; calib_tsens_point1_data[3] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens3_point1; calib_tsens_point1_data[4] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens4_point1; calib_tsens_point1_data[5] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens5_point1; calib_tsens_point1_data[6] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens6_point1; calib_tsens_point1_data[7] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens7_point1; calib_tsens_point1_data[8] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens8_point1; calib_tsens_point1_data[9] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens9_point1; calib_tsens_point1_data[10] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens10_point1; } if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) || (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) { pr_debug("one point calibration calculation\n"); calib_tsens_point1_data[0] = ((((tsens_base1_data) + tsens0_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[1] = ((((tsens_base1_data) + tsens1_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[2] = ((((tsens_base1_data) + tsens2_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[3] = ((((tsens_base1_data) + tsens3_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[4] = ((((tsens_base1_data) + tsens4_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[5] = ((((tsens_base1_data) + tsens5_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[6] = ((((tsens_base1_data) + tsens6_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[7] = ((((tsens_base1_data) + tsens7_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[8] = ((((tsens_base1_data) + tsens8_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[9] = ((((tsens_base1_data) + tsens9_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[10] = ((((tsens_base1_data) + tsens10_point1) << 2) | TSENS_BIT_APPEND); } if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { pr_debug("two point calibration calculation\n"); calib_tsens_point2_data[0] = (((tsens_base2_data + tsens0_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[1] = (((tsens_base2_data + tsens1_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[2] = (((tsens_base2_data + tsens2_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[3] = (((tsens_base2_data + tsens3_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[4] = (((tsens_base2_data + tsens4_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[5] = (((tsens_base2_data + tsens5_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[6] = (((tsens_base2_data + tsens6_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[7] = (((tsens_base2_data + tsens7_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[8] = (((tsens_base2_data + tsens8_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[9] = (((tsens_base2_data + tsens9_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[10] = (((tsens_base2_data + tsens10_point2) << 2) | TSENS_BIT_APPEND); } 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", 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\n", tmdev->sensor[i].offset); tmdev->prev_reading_avail = false; } return 0; } static int tsens_calib_9900_sensors(void) { int i, tsens_base1_data = 0, tsens0_point1 = 0, tsens1_point1 = 0; int tsens2_point1 = 0, tsens3_point1 = 0, tsens4_point1 = 0; int tsens5_point1 = 0, tsens6_point1 = 0, tsens0_point2 = 0; int tsens1_point2 = 0, tsens2_point2 = 0, tsens3_point2 = 0; int tsens4_point2 = 0, tsens5_point2 = 0, tsens6_point2 = 0; int tsens_base2_data = 0, tsens_calibration_mode = 0; uint32_t calib_data[4], calib_redun_sel, calib_data_backup[4]; uint32_t calib_tsens_point1_data[7], calib_tsens_point2_data[7]; if (tmdev->calibration_less_mode) goto calibration_less_mode; calib_redun_sel = readl_relaxed( TSENS_9900_EEPROM_REDUNDANCY_SEL(tmdev->tsens_calib_addr)); calib_redun_sel = calib_redun_sel & TSENS_QFPROM_BACKUP_9900_REDUN_SEL; calib_redun_sel >>= TSENS_QFPROM_BACKUP_9900_REDUN_SHIFT; pr_debug("calib_redun_sel:%x\n", calib_redun_sel); if (calib_redun_sel == TSENS_QFPROM_BACKUP_SEL) { for (i = 0; i < TSENS_9900_CALIB_ADDR_RANGE; i++) { calib_data_backup[i] = readl_relaxed( (TSENS_9900_EEPROM_BACKUP_REGION( tmdev->tsens_calib_addr)) + (i * TSENS_SN_ADDR_OFFSET)); pr_debug("backup calib raw data row%d:0x%x\n", i, calib_data_backup[i]); } tsens_calibration_mode = (calib_data_backup[0] & TSENS_9900_TSENS_CAL_SEL) >> TSENS_9900_CAL_SEL_SHIFT; pr_debug("backup calib mode:%x\n", tsens_calibration_mode); if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB) || (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) || (tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) { tsens_base1_data = (calib_data_backup[0] & TSENS_9900_BASE1_MASK); tsens0_point1 = (calib_data_backup[0] & TSENS0_9900_POINT1_MASK) >> TSENS0_9900_POINT1_SHIFT; tsens1_point1 = (calib_data_backup[1] & TSENS1_9900_POINT1_MASK); tsens2_point1 = (calib_data_backup[1] & TSENS2_9900_POINT1_MASK) >> TSENS2_9900_POINT1_SHIFT; tsens3_point1 = (calib_data_backup[1] & TSENS3_9900_POINT1_MASK) >> TSENS3_9900_POINT1_SHIFT; tsens4_point1 = (calib_data_backup[2] & TSENS4_9900_POINT1_MASK) >> TSENS4_9900_POINT1_SHIFT; tsens5_point1 = (calib_data_backup[2] & TSENS5_9900_POINT1_MASK) >> TSENS5_9900_POINT1_SHIFT; tsens6_point1 = (calib_data_backup[3] & TSENS6_9900_POINT1_MASK); } else goto calibration_less_mode; if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { tsens_base2_data = (calib_data_backup[0] & TSENS_9900_BASE2_MASK) >> TSENS_9900_BASE2_SHIFT; tsens0_point2 = (calib_data_backup[0] & TSENS0_9900_POINT2_MASK) >> TSENS0_9900_POINT2_SHIFT; tsens1_point2 = (calib_data_backup[1] & TSENS1_9900_POINT2_MASK)>> TSENS1_9900_POINT2_SHIFT; tsens2_point2 = (calib_data_backup[1] & TSENS2_9900_POINT2_MASK) >> TSENS2_9900_POINT2_SHIFT; tsens3_point2 = (calib_data_backup[2] & TSENS3_9900_POINT2_MASK); tsens4_point2 = (calib_data_backup[2] & TSENS4_9900_POINT2_MASK) >> TSENS4_9900_POINT2_SHIFT; tsens5_point2 = (calib_data_backup[2] & TSENS5_9900_POINT2_MASK) >> TSENS5_9900_POINT2_SHIFT; tsens6_point2 = (calib_data_backup[3] & TSENS6_9900_POINT2_MASK) >> TSENS6_9900_POINT2_SHIFT; } } else { for (i = 0; i < TSENS_9900_CALIB_ADDR_RANGE; i++) { calib_data[i] = readl_relaxed( (TSENS_9900_EEPROM(tmdev->tsens_calib_addr)) + (i * TSENS_SN_ADDR_OFFSET)); pr_debug("calib raw data row%d:0x%x\n", i , calib_data[i]); } tsens_calibration_mode = (calib_data[0] & TSENS_9900_TSENS_CAL_SEL) >> TSENS_9900_CAL_SEL_SHIFT; pr_debug("calib mode:%x\n", tsens_calibration_mode); if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB) || (tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) || (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) { tsens_base1_data = (calib_data[0] & TSENS_9900_BASE1_MASK); tsens0_point1 = (calib_data[0] & TSENS0_9900_POINT1_MASK) >> TSENS0_9900_POINT1_SHIFT; tsens1_point1 = (calib_data[1] & TSENS1_9900_POINT1_MASK); tsens2_point1 = (calib_data[1] & TSENS2_9900_POINT1_MASK) >> TSENS2_9900_POINT1_SHIFT; tsens3_point1 = (calib_data[1] & TSENS3_9900_POINT1_MASK) >> TSENS3_9900_POINT1_SHIFT; tsens4_point1 = (calib_data[2] & TSENS4_9900_POINT1_MASK) >> TSENS4_9900_POINT1_SHIFT; tsens5_point1 = (calib_data[2] & TSENS5_9900_POINT1_MASK) >> TSENS5_9900_POINT1_SHIFT; tsens6_point1 = (calib_data[3] & TSENS6_9900_POINT1_MASK); } else goto calibration_less_mode; if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { tsens_base2_data = (calib_data[0] & TSENS_9900_BASE2_MASK) >> TSENS_9900_BASE2_SHIFT; tsens0_point2 = (calib_data[0] & TSENS0_9900_POINT2_MASK) >> TSENS0_9900_POINT2_SHIFT; tsens1_point2 = (calib_data[1] & TSENS1_9900_POINT2_MASK) >> TSENS1_9900_POINT2_SHIFT; tsens2_point2 = (calib_data[1] & TSENS2_9900_POINT2_MASK)>> TSENS2_9900_POINT2_SHIFT; tsens3_point2 = (calib_data[2] & TSENS3_9900_POINT2_MASK); tsens4_point2 = (calib_data[2] & TSENS4_9900_POINT2_MASK) >> TSENS4_9900_POINT2_SHIFT; tsens5_point2 = (calib_data[2] & TSENS5_9900_POINT2_MASK) >> TSENS5_9900_POINT2_SHIFT; tsens6_point2 = (calib_data[3] & TSENS6_9900_POINT2_MASK) >> TSENS6_9900_POINT2_SHIFT; } if (tsens_calibration_mode == 0) { calibration_less_mode: pr_debug("TSENS is calibrationless mode\n"); for (i = 0; i < tmdev->tsens_num_sensor; i++) calib_tsens_point2_data[i] = 780; calib_tsens_point1_data[0] = 502; calib_tsens_point1_data[1] = 509; calib_tsens_point1_data[2] = 503; calib_tsens_point1_data[3] = 509; calib_tsens_point1_data[4] = 505; calib_tsens_point1_data[5] = 509; calib_tsens_point1_data[6] = 507; goto compute_intercept_slope; } } if (tsens_calibration_mode == TSENS_ONE_POINT_CALIB) { calib_tsens_point1_data[0] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens0_point1; calib_tsens_point1_data[1] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens1_point1; calib_tsens_point1_data[2] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens2_point1; calib_tsens_point1_data[3] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens3_point1; calib_tsens_point1_data[4] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens4_point1; calib_tsens_point1_data[5] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens5_point1; calib_tsens_point1_data[6] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens6_point1; } if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) || (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) { pr_debug("one point calibration calculation\n"); calib_tsens_point1_data[0] = ((((tsens_base1_data) + tsens0_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[1] = ((((tsens_base1_data) + tsens1_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[2] = ((((tsens_base1_data) + tsens2_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[3] = ((((tsens_base1_data) + tsens3_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[4] = ((((tsens_base1_data) + tsens4_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[5] = ((((tsens_base1_data) + tsens5_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[6] = ((((tsens_base1_data) + tsens6_point1) << 2) | TSENS_BIT_APPEND); } if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { pr_debug("two point calibration calculation\n"); calib_tsens_point2_data[0] = (((tsens_base2_data + tsens0_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[1] = (((tsens_base2_data + tsens1_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[2] = (((tsens_base2_data + tsens2_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[3] = (((tsens_base2_data + tsens3_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[4] = (((tsens_base2_data + tsens4_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[5] = (((tsens_base2_data + tsens5_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[6] = (((tsens_base2_data + tsens6_point2) << 2) | TSENS_BIT_APPEND); } 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", 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\n", tmdev->sensor[i].offset); tmdev->prev_reading_avail = false; } return 0; } static int tsens_calib_9010_sensors(void) { int i, tsens_base1_data = 0, tsens_base2_data = 0; int tsens0_point1 = 0, tsens1_point1 = 0, tsens2_point1 = 0; int tsens0_point2 = 0, tsens1_point2 = 0, tsens2_point2 = 0; int tsens_calibration_mode = 0; uint32_t calib_data[4], calib_redun_sel, calib_data_backup[4]; uint32_t calib_tsens_point1_data[3], calib_tsens_point2_data[3]; if (tmdev->calibration_less_mode) goto calibration_less_mode; calib_redun_sel = readl_relaxed( TSENS_9010_EEPROM_REDUNDANCY_SEL(tmdev->tsens_calib_addr)); calib_redun_sel = calib_redun_sel & TSENS_QFPROM_BACKUP_9010_REDUN_SEL; calib_redun_sel >>= TSENS_QFPROM_BACKUP_9010_REDUN_SHIFT; pr_debug("calib_redun_sel:%x\n", calib_redun_sel); if (calib_redun_sel == TSENS_QFPROM_BACKUP_SEL) { for (i = 0; i < TSENS_9010_CALIB_ADDR_RANGE; i++) { calib_data_backup[i] = readl_relaxed( (TSENS_9010_EEPROM_BACKUP_REGION( tmdev->tsens_calib_addr)) + (i * TSENS_SN_ADDR_OFFSET)); pr_debug("backup calib raw data row%d:0x%x\n", i, calib_data_backup[i]); } tsens_calibration_mode = (calib_data_backup[0] & TSENS_9010_TSENS_CAL_SEL) >> TSENS_9010_CAL_SEL_SHIFT; pr_debug("backup calib mode:%x\n", tsens_calibration_mode); if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB) || (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) || (tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2)) { tsens_base1_data = (calib_data_backup[0] & TSENS_9010_BASE1_MASK); tsens0_point1 = (calib_data_backup[0] & TSENS0_9010_POINT1_MASK) >> TSENS0_9010_POINT1_SHIFT; tsens1_point1 = (calib_data_backup[1] & TSENS1_9010_POINT1_MASK); tsens2_point1 = (calib_data_backup[1] & TSENS2_9010_POINT1_MASK) >> TSENS2_9010_POINT1_SHIFT; } else goto calibration_less_mode; if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { tsens_base2_data = (calib_data_backup[0] & TSENS_9010_BASE2_MASK) >> TSENS_9010_BASE2_SHIFT; tsens0_point2 = (calib_data_backup[0] & TSENS0_9010_POINT2_MASK) >> TSENS0_9010_POINT2_SHIFT; tsens1_point2 = (calib_data_backup[1] & TSENS1_9010_POINT2_MASK)>> TSENS1_9010_POINT2_SHIFT; tsens2_point2 = (calib_data_backup[1] & TSENS2_9010_POINT2_MASK) >> TSENS2_9010_POINT2_SHIFT; } } else { for (i = 0; i < TSENS_9010_CALIB_ADDR_RANGE; i++) { calib_data[i] = readl_relaxed( (TSENS_9010_EEPROM(tmdev->tsens_calib_addr)) + (i * TSENS_SN_ADDR_OFFSET)); pr_debug("calib raw data row%d:0x%x\n", i , calib_data[i]); } tsens_calibration_mode = (calib_data[0] & TSENS_9010_TSENS_CAL_SEL) >> TSENS_9010_CAL_SEL_SHIFT; pr_debug("calib mode:%x\n", tsens_calibration_mode); if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB) || (tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) || (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) { tsens_base1_data = (calib_data[0] & TSENS_9010_BASE1_MASK); tsens0_point1 = (calib_data[0] & TSENS0_9010_POINT1_MASK) >> TSENS0_9010_POINT1_SHIFT; tsens1_point1 = (calib_data[1] & TSENS1_9010_POINT1_MASK); tsens2_point1 = (calib_data[1] & TSENS2_9010_POINT1_MASK) >> TSENS2_9010_POINT1_SHIFT; } else goto calibration_less_mode; if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { tsens_base2_data = (calib_data[0] & TSENS_9010_BASE2_MASK) >> TSENS_9010_BASE2_SHIFT; tsens0_point2 = (calib_data[0] & TSENS0_9010_POINT2_MASK) >> TSENS0_9010_POINT2_SHIFT; tsens1_point2 = (calib_data[1] & TSENS1_9010_POINT2_MASK) >> TSENS1_9010_POINT2_SHIFT; tsens2_point2 = (calib_data[1] & TSENS2_9010_POINT2_MASK)>> TSENS2_9010_POINT2_SHIFT; } if (tsens_calibration_mode == 0) { calibration_less_mode: pr_debug("TSENS is calibrationless mode\n"); for (i = 0; i < tmdev->tsens_num_sensor; i++) calib_tsens_point2_data[i] = 684; calib_tsens_point1_data[0] = 418; calib_tsens_point1_data[1] = 418; calib_tsens_point1_data[2] = 418; goto compute_intercept_slope; } } if (tsens_calibration_mode == TSENS_ONE_POINT_CALIB) { calib_tsens_point1_data[0] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens0_point1; calib_tsens_point1_data[1] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens1_point1; calib_tsens_point1_data[2] = (((tsens_base1_data) << 2) | TSENS_BIT_APPEND) + tsens2_point1; } if ((tsens_calibration_mode == TSENS_ONE_POINT_CALIB_OPTION_2) || (tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) { pr_debug("one point calibration calculation\n"); calib_tsens_point1_data[0] = ((((tsens_base1_data) + tsens0_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[1] = ((((tsens_base1_data) + tsens1_point1) << 2) | TSENS_BIT_APPEND); calib_tsens_point1_data[2] = ((((tsens_base1_data) + tsens2_point1) << 2) | TSENS_BIT_APPEND); } if (tsens_calibration_mode == TSENS_TWO_POINT_CALIB) { pr_debug("two point calibration calculation\n"); calib_tsens_point2_data[0] = (((tsens_base2_data + tsens0_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[1] = (((tsens_base2_data + tsens1_point2) << 2) | TSENS_BIT_APPEND); calib_tsens_point2_data[2] = (((tsens_base2_data + tsens2_point2) << 2) | TSENS_BIT_APPEND); } 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", 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\n", tmdev->sensor[i].offset); tmdev->prev_reading_avail = false; } return 0; } static int tsens_calib_mdm9640_sensors(void) { int i = 0, tsens_base0_data = 0, tsens_base1_data = 0; int tsens0_point = 0, tsens1_point = 0, tsens2_point = 0; int tsens3_point = 0, tsens4_point = 0; int tsens_calibration_mode = 0; uint32_t calib_data[2] = {0, 0}; uint32_t calib_tsens_point_data[5]; const struct of_device_id *id; struct device_node *of_node; 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; } else { id = of_match_node(tsens_match, of_node); if (id == NULL) { pr_err("can not find tsens_match of_node\n"); return -ENODEV; } } if (!tmdev->calibration_less_mode) { if (!strcmp(id->compatible, "qcom,mdm9640v2-tsens")) { calib_data[0] = readl_relaxed( TSENS_EEPROM_9640V2(tmdev->tsens_calib_addr)); calib_data[1] = readl_relaxed( (TSENS_EEPROM_9640V2(tmdev->tsens_calib_addr) + 0x4)); tsens_calibration_mode = (calib_data[1] & TSENS_9640_CAL_SEL) >> TSENS_9640_CAL_SEL_SHIFT; pr_debug("calib mode is %d\n", tsens_calibration_mode); } else { calib_data[0] = readl_relaxed( TSENS_EEPROM(tmdev->tsens_calib_addr)); calib_data[1] = readl_relaxed( (TSENS_EEPROM(tmdev->tsens_calib_addr) + 0x4)); tsens_calibration_mode = (calib_data[1] & TSENS_9640_CAL_SEL) >> TSENS_9640_CAL_SEL_SHIFT; pr_debug("calib mode is %d\n", tsens_calibration_mode); } } if ((tsens_calibration_mode == TSENS_TWO_POINT_CALIB)) { tsens_base0_data = (calib_data[0] & TSENS_BASE0_9640_MASK); tsens_base1_data = (calib_data[0] & TSENS_BASE1_9640_MASK) >> TSENS_BASE1_9640_SHIFT; tsens0_point = (calib_data[0] & TSENS0_OFFSET_9640_MASK) >> TSENS0_OFFSET_9640_SHIFT; tsens1_point = (calib_data[0] & TSENS1_OFFSET_9640_MASK) >> TSENS1_OFFSET_9640_SHIFT; tsens2_point = (calib_data[0] & TSENS2_OFFSET_9640_MASK) >> TSENS2_OFFSET_9640_SHIFT; tsens3_point = (calib_data[1] & TSENS3_OFFSET_9640_MASK); tsens4_point = (calib_data[1] & TSENS4_OFFSET_9640_MASK) >> TSENS4_OFFSET_9640_SHIFT; calib_tsens_point_data[0] = tsens0_point; calib_tsens_point_data[1] = tsens1_point; calib_tsens_point_data[2] = tsens2_point; calib_tsens_point_data[3] = tsens3_point; calib_tsens_point_data[4] = tsens4_point; } else { if (tsens_calibration_mode == 0) { pr_debug("TSENS is calibrationless mode\n"); calib_tsens_point_data[0] = 532; calib_tsens_point_data[1] = 532; calib_tsens_point_data[2] = 532; calib_tsens_point_data[3] = 532; calib_tsens_point_data[4] = 532; } } 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", 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; } adc_code_of_tempx = tsens_base0_data + calib_tsens_point_data[i]; pr_debug("offset_adc_code_of_tempx:0x%x\n", adc_code_of_tempx); tmdev->sensor[i].offset = (adc_code_of_tempx * 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_sensors(void) { int rc = 0; if (!tmdev) return -ENODEV; if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8974) rc = tsens_calib_8974_sensors(); else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8X26) rc = tsens_calib_8x26_sensors(); else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8X10) rc = tsens_calib_8x10_sensors(); else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_9900) rc = tsens_calib_9900_sensors(); else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_9010) rc = tsens_calib_9010_sensors(); else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_9630) rc = tsens_calib_9630_sensors(); else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8916) rc = tsens_calib_8916_sensors(); else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8939) rc = tsens_calib_8939_sensors(); else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8994) rc = tsens_calib_8994_sensors(); else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_MSM8909) rc = tsens_calib_msm8909_sensors(); else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_MDM9640) rc = tsens_calib_mdm9640_sensors(); else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_8992) rc = tsens_calib_8992_sensors(); else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_MSM8952) rc = tsens_calib_msm8952_sensors(); else if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_GENERIC_A) rc = tsens_generic_dt_calib_type_a(); else { pr_err("TSENS Calib fuse not found\n"); rc = -ENODEV; } return rc; } int get_calibraion_data(struct platform_device *pdev) { struct device_node *of_node = pdev->dev.of_node; u32 rc = 0; u32 tsens_base_info[2] = {0 , 0}; u32 base_bit_size = 0, no_of_base = 0; u32 tsens_sensor_point1_masks = 0, tsens_sensor_point2_masks = 0; u32 tsens_sensor_bit_size = 0, tsens_calib_mask_info = 1; struct mask_info *tsens_base_mask, *tsens_calib_mask; rc = of_property_read_u32_array(of_node, "qcom,tsens_base_info", tsens_base_info, sizeof(tsens_base_info)/sizeof(u32)); if (rc) { dev_err(&pdev->dev, "missing tsens_base_info"); return rc; } no_of_base = tsens_base_info[0]; base_bit_size = tsens_base_info[1]; tsens_base_mask = devm_kzalloc(&pdev->dev, no_of_base * sizeof(struct mask_info), GFP_KERNEL); if (!tsens_base_mask) { dev_err(&pdev->dev, "can not allocate base_mask"); return -ENOMEM; } rc = of_property_read_u32_array(of_node, "qcom,tsens_base_mask", (u32 *) tsens_base_mask, no_of_base * sizeof(struct mask_info)/sizeof(u32)); if (rc) { dev_err(&pdev->dev, "missing tsens_base_mask"); return rc; } rc = of_property_read_u32(of_node, "qcom,tsens_calib_mask_info", &tsens_calib_mask_info); if (rc) { dev_info(&pdev->dev, "tsens_calib_mask_info not set"); tsens_calib_mask_info = 1; } tsens_calib_mask = devm_kzalloc(&pdev->dev, tsens_calib_mask_info * sizeof(struct mask_info), GFP_KERNEL); if (!tsens_calib_mask) { dev_err(&pdev->dev, "can not allocate tsens_calib_mask"); return -ENOMEM; } rc = of_property_read_u32_array(of_node, "qcom,tsens_calib_mask", (u32 *) tsens_calib_mask, tsens_calib_mask_info * sizeof(struct mask_info)/sizeof(u32)); if (rc) { dev_err(&pdev->dev, "missing tsens_calib_mask"); return rc; } rc = of_property_read_u32(of_node, "qcom,tsens_sensor_point_bit_size", &tsens_sensor_bit_size); if (rc) { dev_err(&pdev->dev, "missing tsens_sensor_point_bit_size"); return rc; } rc = of_property_read_u32(of_node, "qcom,tsens_sensor_point1_total_masks", &tsens_sensor_point1_masks); if (rc) { dev_err(&pdev->dev, "missing tsens_sensor_point1_total_masks"); return rc; } tmdev->tsens_point1_mask = devm_kzalloc(&pdev->dev, tsens_sensor_point1_masks * sizeof(struct mask_info), GFP_KERNEL); if (!tmdev->tsens_point1_mask) { dev_err(&pdev->dev, "can not allocate tsens_point1_mask"); return -ENOMEM; } rc = of_property_read_u32_array(of_node, "qcom,tsens_sensor_point1", (u32 *) tmdev->tsens_point1_mask, tsens_sensor_point1_masks * sizeof(struct mask_info) / sizeof(u32)); if (rc) { dev_err(&pdev->dev, "missing tsens_sensor_point1"); return rc; } rc = of_property_read_u32(of_node, "qcom,tsens_sensor_point2_total_masks", &tsens_sensor_point2_masks); if (rc) { dev_err(&pdev->dev, "missing tsens_sensor_point2_total_masks"); return rc; } tmdev->tsens_point2_mask = devm_kzalloc(&pdev->dev, tsens_sensor_point2_masks * sizeof(struct mask_info), GFP_KERNEL); if (!tmdev->tsens_point2_mask) { dev_err(&pdev->dev, "can not allocate tsens_point2_mask"); return -ENOMEM; } rc = of_property_read_u32_array(of_node, "qcom,tsens_sensor_point2", (u32 *) tmdev->tsens_point2_mask, tsens_sensor_point2_masks * sizeof(struct mask_info) / sizeof(u32)); if (rc) { dev_err(&pdev->dev, "missing tsens_sensor_point2"); return rc; } tmdev->tsens_no_of_base = no_of_base; tmdev->tsens_base_bit_size = base_bit_size; tmdev->tsens_base_mask = tsens_base_mask; tmdev->tsens_calib_mask_info = tsens_calib_mask_info; tmdev->tsens_calib_mask = tsens_calib_mask; tmdev->tsens_sensor_bit_size = tsens_sensor_bit_size; tmdev->tsens_sensor_point1_masks = tsens_sensor_point1_masks; tmdev->tsens_sensor_point2_masks = tsens_sensor_point2_masks; return rc; } static int get_device_tree_data(struct platform_device *pdev) { struct device_node *of_node = pdev->dev.of_node; struct resource *res_mem = NULL; u32 *tsens_slope_data, *sensor_id; u32 rc = 0, i = 0, tsens_num_sensors = 0; u32 tsens_calib_mask_info = 1; const struct of_device_id *id; rc = of_property_read_u32(of_node, "qcom,sensors", &tsens_num_sensors); if (rc) { dev_err(&pdev->dev, "missing sensor number\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"); return -ENOMEM; } rc = of_property_read_u32_array(of_node, "qcom,slope", tsens_slope_data, tsens_num_sensors); if (rc) { dev_err(&pdev->dev, "invalid or missing property: tsens-slope\n"); return rc; }; 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; } for (i = 0; i < tsens_num_sensors; i++) tmdev->sensor[i].slope_mul_tsens_factor = tsens_slope_data[i]; tmdev->tsens_factor = TSENS_SLOPE_FACTOR; tmdev->tsens_num_sensor = tsens_num_sensors; tmdev->calibration_less_mode = of_property_read_bool(of_node, "qcom,calibration-less-mode"); tmdev->tsens_local_init = of_property_read_bool(of_node, "qcom,tsens-local-init"); tmdev->calib_mode = (u32)(uintptr_t) id->data; if (tmdev->calib_mode == TSENS_CALIB_FUSE_MAP_GENERIC_A) { rc = get_calibraion_data(pdev); if (rc) { dev_err(&pdev->dev, "get_calibraion_data failed"); return rc; } } else { tmdev->tsens_no_of_base = 0; tmdev->tsens_base_bit_size = 0; tmdev->tsens_base_mask = NULL; tmdev->tsens_calib_mask = NULL; tmdev->tsens_point1_mask = NULL; tmdev->tsens_point2_mask = NULL; tmdev->tsens_calib_mask_info = tsens_calib_mask_info; tmdev->tsens_sensor_bit_size = 0; tmdev->tsens_sensor_point1_masks = 0; tmdev->tsens_sensor_point2_masks = 0; } 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"); return -ENOMEM; } rc = of_property_read_u32_array(of_node, "qcom,sensor-id", sensor_id, tsens_num_sensors); if (rc) { pr_debug("Default sensor id mapping\n"); for (i = 0; i < tsens_num_sensors; i++) { tmdev->sensor[i].sensor_hw_num = i; tmdev->sensor[i].sensor_sw_id = i; } } else { pr_debug("Use specified sensor id mapping\n"); for (i = 0; i < tsens_num_sensors; i++) { tmdev->sensor[i].sensor_hw_num = sensor_id[i]; tmdev->sensor[i].sensor_sw_id = i; } } if (!strcmp(id->compatible, "qcom,mdm9630-tsens") || (!strcmp(id->compatible, "qcom,mdm9640-tsens")) || (!strcmp(id->compatible, "qcom,msm8994-tsens")) || (!strcmp(id->compatible, "qcom,msm8992-tsens")) || (!strcmp(id->compatible, "qcom,mdm9640v2-tsens"))) tmdev->tsens_type = TSENS_TYPE2; else if (!strcmp(id->compatible, "qcom,msm8952-tsens") || (!strcmp(id->compatible, "qcom,msm8976-tsens"))) tmdev->tsens_type = TSENS_TYPE3; else tmdev->tsens_type = TSENS_TYPE0; if (!strcmp(id->compatible, "qcom,msm8994-tsens") || (!strcmp(id->compatible, "qcom,msm8992-tsens")) || (!strcmp(id->compatible, "qcom,mdm9640-tsens")) || (!strcmp(id->compatible, "qcom,msm8952-tsens")) || (!strcmp(id->compatible, "qcom,msm8976-tsens")) || (!strcmp(id->compatible, "qcom,mdm9640v2-tsens"))) tmdev->tsens_valid_status_check = true; else tmdev->tsens_valid_status_check = false; tmdev->tsens_irq = platform_get_irq_byname(pdev, "tsens-upper-lower"); if (tmdev->tsens_irq < 0) { pr_err("Invalid Upper/Lower irq\n"); rc = tmdev->tsens_irq; goto fail_tmdev; } /* TSENS register region */ tmdev->res_tsens_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tsens_physical"); if (!tmdev->res_tsens_mem) { pr_err("Could not get tsens physical address resource\n"); rc = -EINVAL; goto fail_tmdev; } tmdev->tsens_len = tmdev->res_tsens_mem->end - tmdev->res_tsens_mem->start + 1; res_mem = request_mem_region(tmdev->res_tsens_mem->start, tmdev->tsens_len, tmdev->res_tsens_mem->name); if (!res_mem) { pr_err("Request tsens physical memory region failed\n"); rc = -EINVAL; goto fail_tmdev; } tmdev->tsens_addr = ioremap(res_mem->start, tmdev->tsens_len); if (!tmdev->tsens_addr) { pr_err("Failed to IO map TSENS registers.\n"); rc = -EINVAL; goto fail_unmap_tsens_region; } /* TSENS calibration region */ tmdev->res_calib_mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tsens_eeprom_physical"); if (!tmdev->res_calib_mem) { pr_err("Could not get qfprom physical address resource\n"); rc = -EINVAL; goto fail_unmap_tsens; } 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->calib_len); if (!tmdev->tsens_calib_addr) { pr_err("Failed to IO map EEPROM registers.\n"); rc = -EINVAL; goto fail_unmap_calib_region; } 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); fail_unmap_tsens_region: if (tmdev->res_tsens_mem) release_mem_region(tmdev->res_tsens_mem->start, tmdev->tsens_len); fail_tmdev: tmdev = NULL; return rc; } static int tsens_tm_probe(struct platform_device *pdev) { int rc, i; if (tmdev) { pr_err("TSENS device already in use\n"); return -EBUSY; } if (pdev->dev.of_node) { rc = get_device_tree_data(pdev); if (rc) { pr_err("Error reading TSENS DT\n"); return rc; } } else return -ENODEV; tmdev->pdev = pdev; rc = tsens_calib_sensors(); if (rc < 0) { pr_err("Calibration failed\n"); goto fail; } tsens_hw_init(); tmdev->prev_reading_avail = true; for (i = 0; i < 16; i++) tmdev->sensor_dbg_info[i].idx = 0; tmdev->is_ready = true; 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_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; return rc; } static int _tsens_register_thermal(void) { struct platform_device *pdev; int rc, i; if (tsens_is_ready() <= 0) { pr_err("%s: TSENS early init not done\n", __func__); return -ENODEV; } pdev = tmdev->pdev; 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); tmdev->sensor[i].mode = THERMAL_DEVICE_ENABLED; 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__); rc = -ENODEV; goto fail; } } rc = request_threaded_irq(tmdev->tsens_irq, NULL, 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++) thermal_zone_device_unregister(tmdev->sensor[i].tz_dev); goto fail; } else { enable_irq_wake(tmdev->tsens_irq); } 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) release_mem_region(tmdev->res_tsens_mem->start, tmdev->tsens_len); return rc; } static int tsens_tm_remove(struct platform_device *pdev) { struct tsens_tm_device *tmdev = platform_get_drvdata(pdev); int i; for (i = 0; i < tmdev->tsens_num_sensor; i++) 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) release_mem_region(tmdev->res_tsens_mem->start, tmdev->tsens_len); free_irq(tmdev->tsens_irq, tmdev); platform_set_drvdata(pdev, NULL); return 0; } static struct platform_driver tsens_tm_driver = { .probe = tsens_tm_probe, .remove = tsens_tm_remove, .driver = { .name = "msm-tsens", .owner = THIS_MODULE, .of_match_table = tsens_match, }, }; int __init tsens_tm_init_driver(void) { return platform_driver_register(&tsens_tm_driver); } arch_initcall(tsens_tm_init_driver); static int __init tsens_thermal_register(void) { return _tsens_register_thermal(); } module_init(tsens_thermal_register); static void __exit _tsens_tm_remove(void) { platform_driver_unregister(&tsens_tm_driver); } module_exit(_tsens_tm_remove); MODULE_ALIAS("platform:" TSENS_DRIVER_NAME); MODULE_LICENSE("GPL v2");