diff --git a/drivers/thermal/msm8960_tsens.c b/drivers/thermal/msm8960_tsens.c index 2a2166a0398..12edb3e418b 100644 --- a/drivers/thermal/msm8960_tsens.c +++ b/drivers/thermal/msm8960_tsens.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -56,10 +57,12 @@ enum tsens_trip_type { #define SENSOR4_EN BIT(7) #define SENSORS_EN (SENSOR0_EN | SENSOR1_EN | \ SENSOR2_EN | SENSOR3_EN | SENSOR4_EN) -#define TSENS_MIN_STATUS_MASK BIT(8) -#define TSENS_LOWER_STATUS_CLR BIT(9) -#define TSENS_UPPER_STATUS_CLR BIT(10) -#define TSENS_MAX_STATUS_MASK BIT(11) +#define TSENS_STATUS_CNTL_OFFSET 8 +#define TSENS_MIN_STATUS_MASK BIT((tsens_status_cntl_start)) +#define TSENS_LOWER_STATUS_CLR BIT((tsens_status_cntl_start + 1)) +#define TSENS_UPPER_STATUS_CLR BIT((tsens_status_cntl_start + 2)) +#define TSENS_MAX_STATUS_MASK BIT((tsens_status_cntl_start + 3)) + #define TSENS_MEASURE_PERIOD 4 /* 1 sec. default */ #define TSENS_8960_SLP_CLK_ENA BIT(26) @@ -86,6 +89,7 @@ enum tsens_trip_type { #define TSENS_S0_STATUS_ADDR (MSM_CLK_CTL_BASE + 0x00003628) #define TSENS_STATUS_ADDR_OFFSET 2 +#define TSENS_SENSOR_STATUS_SIZE 4 #define TSENS_INT_STATUS_ADDR (MSM_CLK_CTL_BASE + 0x0000363c) #define TSENS_LOWER_INT_MASK BIT(1) @@ -113,6 +117,26 @@ enum tsens_trip_type { #define TSENS_8660_CONFIG_MASK (3 << TSENS_8660_CONFIG_SHIFT) #define TSENS_8660_SLP_CLK_ENA BIT(24) +#define TSENS_8064_SENSOR5_EN BIT(8) +#define TSENS_8064_SENSOR6_EN BIT(9) +#define TSENS_8064_SENSOR7_EN BIT(10) +#define TSENS_8064_SENSOR8_EN BIT(11) +#define TSENS_8064_SENSOR9_EN BIT(12) +#define TSENS_8064_SENSOR10_EN BIT(13) +#define TSENS_8064_SENSORS_EN (SENSORS_EN | \ + TSENS_8064_SENSOR5_EN | \ + TSENS_8064_SENSOR6_EN | \ + TSENS_8064_SENSOR7_EN | \ + TSENS_8064_SENSOR8_EN | \ + TSENS_8064_SENSOR9_EN | \ + TSENS_8064_SENSOR10_EN) +#define TSENS_8064_STATUS_CNTL (MSM_CLK_CTL_BASE + 0x00003660) +#define TSENS_8064_S5_STATUS_ADDR (MSM_CLK_CTL_BASE + 0x00003664) +#define TSENS_8064_SEQ_SENSORS 5 +#define TSENS_8064_S4_S5_OFFSET 40 + +static int tsens_status_cntl_start; + struct tsens_tm_device_sensor { struct thermal_zone_device *tz_dev; enum thermal_device_mode mode; @@ -121,11 +145,11 @@ struct tsens_tm_device_sensor { int offset; int calib_data; int calib_data_backup; + uint32_t slope_mul_tsens_factor; }; struct tsens_tm_device { bool prev_reading_avail; - int slope_mul_tsens_factor; int tsens_factor; uint32_t tsens_num_sensor; enum platform_type hw_type; @@ -137,26 +161,18 @@ struct tsens_tm_device *tmdev; /* Temperature on y axis and ADC-code on x-axis */ static int tsens_tz_code_to_degC(int adc_code, int sensor_num) { - int degC, degcbeforefactor; - degcbeforefactor = adc_code * tmdev->slope_mul_tsens_factor - + tmdev->sensor[sensor_num].offset; - if (degcbeforefactor == 0) - degC = degcbeforefactor; - else if (degcbeforefactor > 0) - degC = (degcbeforefactor + tmdev->tsens_factor/2) - / tmdev->tsens_factor; - else /* rounding for negative degrees */ - degC = (degcbeforefactor - tmdev->tsens_factor/2) - / tmdev->tsens_factor; - return degC; + int degc; + degc = (adc_code * tmdev->sensor[sensor_num].slope_mul_tsens_factor + + tmdev->sensor[sensor_num].offset) + / tmdev->tsens_factor; + return degc; } static int tsens_tz_degC_to_code(int degC, int sensor_num) { int code = (degC * tmdev->tsens_factor - - tmdev->sensor[sensor_num].offset - + tmdev->slope_mul_tsens_factor/2) - / tmdev->slope_mul_tsens_factor; + tmdev->sensor[sensor_num].offset) + / tmdev->sensor[sensor_num].slope_mul_tsens_factor; if (code > TSENS_THRESHOLD_MAX_CODE) code = TSENS_THRESHOLD_MAX_CODE; @@ -167,7 +183,7 @@ static int tsens_tz_degC_to_code(int degC, int sensor_num) static void tsens8960_get_temp(int sensor_num, unsigned long *temp) { - unsigned int code; + unsigned int code, offset = 0, sensor_addr; if (!tmdev->prev_reading_avail) { while (!(readl_relaxed(TSENS_INT_STATUS_ADDR) @@ -176,7 +192,12 @@ static void tsens8960_get_temp(int sensor_num, unsigned long *temp) TSENS_TRDY_RDY_MAX_TIME); tmdev->prev_reading_avail = true; } - code = readl_relaxed(TSENS_S0_STATUS_ADDR + + + sensor_addr = (unsigned int)TSENS_S0_STATUS_ADDR; + if (tmdev->hw_type == APQ_8064 && + sensor_num >= TSENS_8064_SEQ_SENSORS) + offset = TSENS_8064_S4_S5_OFFSET; + code = readl_relaxed(sensor_addr + offset + (sensor_num << TSENS_STATUS_ADDR_OFFSET)); *temp = tsens_tz_code_to_degC(code, sensor_num); } @@ -247,7 +268,8 @@ static int tsens_tz_set_mode(struct thermal_zone_device *thermal, } writel_relaxed(reg | TSENS_SW_RST, TSENS_CNTL_ADDR); if (tmdev->hw_type == MSM_8960 || - tmdev->hw_type == MSM_9615) + tmdev->hw_type == MSM_9615 || + tmdev->hw_type == APQ_8064) reg |= mask | TSENS_8960_SLP_CLK_ENA | TSENS_EN; else @@ -257,7 +279,11 @@ static int tsens_tz_set_mode(struct thermal_zone_device *thermal, } else { reg &= ~mask; if (!(reg & SENSOR0_EN)) { - if (tmdev->hw_type == MSM_8960 || + if (tmdev->hw_type == APQ_8064) + reg &= ~(TSENS_8064_SENSORS_EN | + TSENS_8960_SLP_CLK_ENA | + TSENS_EN); + else if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615) reg &= ~(SENSORS_EN | TSENS_8960_SLP_CLK_ENA | @@ -319,7 +345,11 @@ static int tsens_tz_activate_trip_type(struct thermal_zone_device *thermal, lo_code = TSENS_THRESHOLD_MIN_CODE; hi_code = TSENS_THRESHOLD_MAX_CODE; - reg_cntl = readl_relaxed(TSENS_CNTL_ADDR); + if (tmdev->hw_type == APQ_8064) + reg_cntl = readl_relaxed(TSENS_8064_STATUS_CNTL); + else + reg_cntl = readl_relaxed(TSENS_CNTL_ADDR); + reg_th = readl_relaxed(TSENS_THRESHOLD_ADDR); switch (trip) { case TSENS_TRIP_STAGE3: @@ -386,14 +416,21 @@ static int tsens_tz_activate_trip_type(struct thermal_zone_device *thermal, return -EINVAL; } - if (mode == THERMAL_TRIP_ACTIVATION_DISABLED) - writel_relaxed(reg_cntl | mask, TSENS_CNTL_ADDR); - else { + if (mode == THERMAL_TRIP_ACTIVATION_DISABLED) { + if (tmdev->hw_type == APQ_8064) + writel_relaxed(reg_cntl | mask, TSENS_8064_STATUS_CNTL); + else + writel_relaxed(reg_cntl | mask, TSENS_CNTL_ADDR); + } else { if (code < lo_code || code > hi_code) { pr_info("%s with invalid code %x\n", __func__, code); return -EINVAL; } - writel_relaxed(reg_cntl & ~mask, TSENS_CNTL_ADDR); + if (tmdev->hw_type == APQ_8064) + writel_relaxed(reg_cntl & ~mask, + TSENS_8064_STATUS_CNTL); + else + writel_relaxed(reg_cntl & ~mask, TSENS_CNTL_ADDR); } mb(); return 0; @@ -465,7 +502,10 @@ static int tsens_tz_set_trip_temp(struct thermal_zone_device *thermal, lo_code = TSENS_THRESHOLD_MIN_CODE; hi_code = TSENS_THRESHOLD_MAX_CODE; - reg_cntl = readl_relaxed(TSENS_CNTL_ADDR); + if (tmdev->hw_type == APQ_8064) + reg_cntl = readl_relaxed(TSENS_8064_STATUS_CNTL); + else + reg_cntl = readl_relaxed(TSENS_CNTL_ADDR); reg_th = readl_relaxed(TSENS_THRESHOLD_ADDR); switch (trip) { case TSENS_TRIP_STAGE3: @@ -561,25 +601,40 @@ static irqreturn_t tsens_isr(int irq, void *data) { struct tsens_tm_device *tm = data; unsigned int threshold, threshold_low, i, code, reg, sensor, mask; + unsigned int sensor_addr; bool upper_th_x, lower_th_x; int adc_code; - reg = readl_relaxed(TSENS_CNTL_ADDR); - writel_relaxed(reg | TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR, - TSENS_CNTL_ADDR); + if (tmdev->hw_type == APQ_8064) { + reg = readl_relaxed(TSENS_8064_STATUS_CNTL); + writel_relaxed(reg | TSENS_LOWER_STATUS_CLR | + TSENS_UPPER_STATUS_CLR, TSENS_8064_STATUS_CNTL); + } else { + reg = readl_relaxed(TSENS_CNTL_ADDR); + writel_relaxed(reg | TSENS_LOWER_STATUS_CLR | + TSENS_UPPER_STATUS_CLR, TSENS_CNTL_ADDR); + } mask = ~(TSENS_LOWER_STATUS_CLR | TSENS_UPPER_STATUS_CLR); threshold = readl_relaxed(TSENS_THRESHOLD_ADDR); threshold_low = (threshold & TSENS_THRESHOLD_LOWER_LIMIT_MASK) >> TSENS_THRESHOLD_LOWER_LIMIT_SHIFT; threshold = (threshold & TSENS_THRESHOLD_UPPER_LIMIT_MASK) >> TSENS_THRESHOLD_UPPER_LIMIT_SHIFT; - reg = sensor = readl_relaxed(TSENS_CNTL_ADDR); - sensor &= (uint32_t) SENSORS_EN; + sensor = readl_relaxed(TSENS_CNTL_ADDR); + if (tmdev->hw_type == APQ_8064) { + reg = readl_relaxed(TSENS_8064_STATUS_CNTL); + sensor &= (uint32_t) TSENS_8064_SENSORS_EN; + } else { + reg = sensor; + sensor &= (uint32_t) SENSORS_EN; + } sensor >>= TSENS_SENSOR0_SHIFT; + sensor_addr = (unsigned int)TSENS_S0_STATUS_ADDR; for (i = 0; i < tmdev->tsens_num_sensor; i++) { + if (i == TSENS_8064_SEQ_SENSORS) + sensor_addr += 40; if (sensor & TSENS_MASK1) { - code = readl_relaxed(TSENS_S0_STATUS_ADDR + - (i << TSENS_STATUS_ADDR_OFFSET)); + code = readl_relaxed(sensor_addr); upper_th_x = code >= threshold; lower_th_x = code <= threshold_low; if (upper_th_x) @@ -589,8 +644,7 @@ static irqreturn_t tsens_isr(int irq, void *data) if (upper_th_x || lower_th_x) { /* Notify user space */ schedule_work(&tm->sensor[i].work); - adc_code = readl_relaxed(TSENS_S0_STATUS_ADDR - + (i << TSENS_STATUS_ADDR_OFFSET)); + adc_code = readl_relaxed(sensor_addr); pr_info("\nTrip point triggered by " "current temperature (%d degrees) " "measured by Temperature-Sensor %d\n", @@ -598,7 +652,11 @@ static irqreturn_t tsens_isr(int irq, void *data) } } sensor >>= 1; + sensor_addr += TSENS_SENSOR_STATUS_SIZE; } + if (tmdev->hw_type == APQ_8064) + writel_relaxed(reg & mask, TSENS_8064_STATUS_CNTL); + else writel_relaxed(reg & mask, TSENS_CNTL_ADDR); mb(); return IRQ_HANDLED; @@ -609,7 +667,8 @@ static void tsens_disable_mode(void) unsigned int reg_cntl = 0; reg_cntl = readl_relaxed(TSENS_CNTL_ADDR); - if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615) + if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615 || + tmdev->hw_type == APQ_8064) writel_relaxed(reg_cntl & ~((((1 << tmdev->tsens_num_sensor) - 1) << TSENS_SENSOR0_SHIFT) | TSENS_8960_SLP_CLK_ENA @@ -624,6 +683,7 @@ static void tsens_disable_mode(void) static void tsens_hw_init(void) { unsigned int reg_cntl = 0, reg_cfg = 0, reg_thr = 0; + unsigned int reg_status_cntl = 0; reg_cntl = readl_relaxed(TSENS_CNTL_ADDR); writel_relaxed(reg_cntl | TSENS_SW_RST, TSENS_CNTL_ADDR); @@ -657,6 +717,25 @@ static void tsens_hw_init(void) (TSENS_8660_CONFIG << TSENS_8660_CONFIG_SHIFT); writel_relaxed(reg_cntl, TSENS_CNTL_ADDR); + } else if (tmdev->hw_type == APQ_8064) { + reg_cntl |= TSENS_8960_SLP_CLK_ENA | + (TSENS_MEASURE_PERIOD << 18) | + (((1 << tmdev->tsens_num_sensor) - 1) << + TSENS_SENSOR0_SHIFT); + writel_relaxed(reg_cntl, TSENS_CNTL_ADDR); + reg_status_cntl = readl_relaxed(TSENS_8064_STATUS_CNTL); + reg_status_cntl |= TSENS_LOWER_STATUS_CLR | + TSENS_UPPER_STATUS_CLR | + TSENS_MIN_STATUS_MASK | + TSENS_MAX_STATUS_MASK; + writel_relaxed(reg_status_cntl, TSENS_8064_STATUS_CNTL); + reg_cntl |= TSENS_EN; + writel_relaxed(reg_cntl, TSENS_CNTL_ADDR); + + reg_cfg = readl_relaxed(TSENS_8960_CONFIG_ADDR); + reg_cfg = (reg_cfg & ~TSENS_8960_CONFIG_MASK) | + (TSENS_8960_CONFIG << TSENS_8960_CONFIG_SHIFT); + writel_relaxed(reg_cfg, TSENS_8960_CONFIG_ADDR); } reg_thr |= (TSENS_LOWER_LIMIT_TH << TSENS_THRESHOLD_LOWER_LIMIT_SHIFT) | @@ -692,8 +771,10 @@ static int tsens_calib_sensors8660(void) } tmdev->sensor[TSENS_MAIN_SENSOR].offset = tmdev->tsens_factor * - TSENS_CAL_DEGC - tmdev->slope_mul_tsens_factor * + TSENS_CAL_DEGC - + tmdev->sensor[TSENS_MAIN_SENSOR].slope_mul_tsens_factor * tmdev->sensor[TSENS_MAIN_SENSOR].calib_data; + tmdev->prev_reading_avail = false; INIT_WORK(&tmdev->sensor[TSENS_MAIN_SENSOR].work, notify_uspace_tsens_fn); @@ -703,35 +784,27 @@ static int tsens_calib_sensors8660(void) static int tsens_calib_sensors8960(void) { - uint32_t *main_sensor_addr, sensor_shift, *backup_sensor_addr; - uint32_t sensor_mask, i; + uint32_t i; + uint8_t *main_sensor_addr, *backup_sensor_addr; for (i = 0; i < tmdev->tsens_num_sensor; i++) { - main_sensor_addr = TSENS_8960_QFPROM_ADDR0 + - (TSENS_8960_QFPROM_SHIFT * - ((i & TSENS_8960_QFPROM_SHIFT) >> TSENS_SENSOR_QFPROM_SHIFT)); - sensor_shift = (i % TSENS_8960_QFPROM_SHIFT) * TSENS_RED_SHIFT; - sensor_mask = TSENS_THRESHOLD_MAX_CODE << sensor_shift; - backup_sensor_addr = TSENS_8960_QFPROM_SPARE_ADDR0 + - (TSENS_8960_QFPROM_SHIFT * - ((i & TSENS_8960_QFPROM_SHIFT) >> TSENS_SENSOR_QFPROM_SHIFT)); + main_sensor_addr = TSENS_8960_QFPROM_ADDR0 + i; + backup_sensor_addr = TSENS_8960_QFPROM_SPARE_ADDR0 + i; - tmdev->sensor[i].calib_data = (readl_relaxed(main_sensor_addr) - & sensor_mask) >> sensor_shift; + tmdev->sensor[i].calib_data = readb_relaxed(main_sensor_addr); tmdev->sensor[i].calib_data_backup = - (readl_relaxed(backup_sensor_addr) & - sensor_mask) >> sensor_shift; + readb_relaxed(backup_sensor_addr); if (tmdev->sensor[i].calib_data_backup) tmdev->sensor[i].calib_data = tmdev->sensor[i].calib_data_backup; - if (!tmdev->sensor[i].calib_data) { WARN(1, "%s: No temperature sensor:%d data for" " calibration in QFPROM!\n", __func__, i); return -ENODEV; } - tmdev->sensor[i].offset = tmdev->tsens_factor * - TSENS_CAL_DEGC - tmdev->slope_mul_tsens_factor * - tmdev->sensor[i].calib_data; + tmdev->sensor[i].offset = (TSENS_CAL_DEGC * + tmdev->tsens_factor) + - (tmdev->sensor[i].calib_data * + tmdev->sensor[i].slope_mul_tsens_factor); tmdev->prev_reading_avail = false; INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn); } @@ -756,7 +829,8 @@ static int tsens_calib_sensors(void) if (tmdev->hw_type == MSM_8660) rc = tsens_calib_sensors8660(); - else if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615) + else if (tmdev->hw_type == MSM_8960 || tmdev->hw_type == MSM_9615 || + tmdev->hw_type == APQ_8064) rc = tsens_calib_sensors8960(); return rc; @@ -764,7 +838,7 @@ static int tsens_calib_sensors(void) int msm_tsens_early_init(struct tsens_platform_data *pdata) { - int rc = 0; + int rc = 0, i; if (!pdata) { pr_err("No TSENS Platform data\n"); @@ -780,7 +854,8 @@ int msm_tsens_early_init(struct tsens_platform_data *pdata) return -ENOMEM; } - tmdev->slope_mul_tsens_factor = pdata->slope; + for (i = 0; i < pdata->tsens_num_sensor; i++) + tmdev->sensor[i].slope_mul_tsens_factor = pdata->slope[i]; tmdev->tsens_factor = pdata->tsens_factor; tmdev->tsens_num_sensor = pdata->tsens_num_sensor; tmdev->hw_type = pdata->hw_type; @@ -799,9 +874,14 @@ int msm_tsens_early_init(struct tsens_platform_data *pdata) return rc; } + if (tmdev->hw_type == APQ_8064) + tsens_status_cntl_start = 0; + else + tsens_status_cntl_start = TSENS_STATUS_CNTL_OFFSET; + tsens_hw_init(); - pr_info("msm_tsens_early_init: done\n"); + pr_debug("msm_tsens_early_init: done\n"); return rc; } @@ -809,6 +889,7 @@ int msm_tsens_early_init(struct tsens_platform_data *pdata) static int __init tsens_tm_init(void) { int rc, i; + unsigned int reg_cntl, reg_status; if (!tmdev) { pr_info("%s : TSENS early init not done.\n", __func__); @@ -823,7 +904,7 @@ static int __init tsens_tm_init(void) tmdev->sensor[i].tz_dev = thermal_zone_device_register(name, TSENS_TRIP_NUM, &tmdev->sensor[i], &tsens_thermal_zone_ops, 0, 0, 0, 0); - if (tmdev->sensor[i].tz_dev == NULL) { + if (IS_ERR(tmdev->sensor[i].tz_dev)) { pr_err("%s: thermal_zone_device_register() failed.\n", __func__); rc = -ENODEV; @@ -841,8 +922,11 @@ static int __init tsens_tm_init(void) goto fail; } - pr_notice("%s: OK\n", __func__); + reg_status = readl_relaxed(TSENS_8064_STATUS_CNTL); + pr_debug("%s: OK\n", __func__); mb(); + reg_status = readl_relaxed(TSENS_8064_STATUS_CNTL); + reg_cntl = readl_relaxed(TSENS_CNTL_ADDR); return 0; fail: tsens_disable_mode(); diff --git a/include/linux/msm_tsens.h b/include/linux/msm_tsens.h index 189548cc69d..99b5acde62a 100644 --- a/include/linux/msm_tsens.h +++ b/include/linux/msm_tsens.h @@ -22,14 +22,15 @@ enum platform_type { MSM_8660 = 0, MSM_8960, MSM_9615, + APQ_8064, MSM_TYPE }; struct tsens_platform_data { - int slope; int tsens_factor; uint32_t tsens_num_sensor; enum platform_type hw_type; + int slope[11]; }; struct tsens_device {