Loading drivers/thermal/msm-tsens.c +31 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,13 @@ static int tsens_get_temp(void *data, int *temp) return tmdev->ops->get_temp(s, temp); } static int tsens_get_min_temp(void *data, int *temp) { struct tsens_sensor *s = data; return tsens_2xxx_get_min_temp(s, temp); } static int tsens_set_trip_temp(void *data, int low_temp, int high_temp) { struct tsens_sensor *s = data; Loading Loading @@ -82,6 +89,9 @@ static const struct of_device_id tsens_table[] = { { .compatible = "qcom,tsens24xx", .data = &data_tsens24xx, }, { .compatible = "qcom,tsens26xx", .data = &data_tsens26xx, }, { .compatible = "qcom,msm8937-tsens", .data = &data_tsens14xx, }, Loading @@ -97,6 +107,10 @@ static struct thermal_zone_of_device_ops tsens_tm_thermal_zone_ops = { .set_trips = tsens_set_trip_temp, }; static struct thermal_zone_of_device_ops tsens_tm_min_thermal_zone_ops = { .get_temp = tsens_get_min_temp, }; static int get_device_tree_data(struct platform_device *pdev, struct tsens_device *tmdev) { Loading @@ -105,6 +119,7 @@ static int get_device_tree_data(struct platform_device *pdev, const struct tsens_data *data; int rc = 0; struct resource *res_tsens_mem; u32 min_temp_id; if (!of_match_node(tsens_table, of_node)) { pr_err("Need to read SoC specific fuse map\n"); Loading Loading @@ -179,6 +194,11 @@ static int get_device_tree_data(struct platform_device *pdev, } } if (!of_property_read_u32(of_node, "0C-sensor-num", &min_temp_id)) tmdev->min_temp_sensor_id = (int)min_temp_id; else tmdev->min_temp_sensor_id = MIN_TEMP_DEF_OFFSET; return rc; } Loading Loading @@ -209,6 +229,17 @@ static int tsens_thermal_zone_register(struct tsens_device *tmdev) return -ENODEV; } if (tmdev->min_temp_sensor_id != MIN_TEMP_DEF_OFFSET) { tmdev->min_temp.tmdev = tmdev; tmdev->min_temp.hw_id = tmdev->min_temp_sensor_id; tmdev->min_temp.tzd = devm_thermal_zone_of_sensor_register( &tmdev->pdev->dev, tmdev->min_temp_sensor_id, &tmdev->min_temp, &tsens_tm_min_thermal_zone_ops); if (IS_ERR(tmdev->min_temp.tzd)) pr_err("Error registering min temp sensor\n"); } /* Register virtual thermal sensors. */ qti_virtual_sensor_register(&tmdev->pdev->dev); Loading drivers/thermal/tsens.h +8 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #define SLOPE_DEFAULT 3200 #define IPC_LOGPAGES 10 #define MIN_TEMP_DEF_OFFSET 0xFF enum tsens_dbg_type { TSENS_DBG_POLL, Loading Loading @@ -208,14 +209,20 @@ struct tsens_device { const struct tsens_data *ctrl_data; struct tsens_mtc_sysfs mtcsys; int trdy_fail_ctr; struct tsens_sensor min_temp; u8 min_temp_sensor_id; struct tsens_sensor sensor[0]; }; extern const struct tsens_data data_tsens2xxx, data_tsens23xx, data_tsens24xx; extern const struct tsens_data data_tsens2xxx, data_tsens23xx, data_tsens24xx, data_tsens26xx; extern const struct tsens_data data_tsens14xx, data_tsens14xx_405; extern struct list_head tsens_device_list; extern int calibrate_8937(struct tsens_device *tmdev); extern int calibrate_405(struct tsens_device *tmdev); extern int tsens_2xxx_get_min_temp( struct tsens_sensor *sensor, int *temp); #endif /* __QCOM_TSENS_H__ */ drivers/thermal/tsens2xxx.c +126 −5 Original line number Diff line number Diff line Loading @@ -42,12 +42,15 @@ #define TSENS_TM_UPPER_LOWER_INT_MASK(n) ((n) + 0x10) #define TSENS_TM_UPPER_INT_SET(n) (1 << (n + 16)) #define TSENS_TM_SN_CRITICAL_THRESHOLD_MASK 0xfff #define TSENS_TM_MIN_TEMP_VALID_BIT BIT(16) #define TSENS_TM_SN_STATUS_VALID_BIT BIT(21) #define TSENS_TM_SN_STATUS_CRITICAL_STATUS BIT(19) #define TSENS_TM_SN_STATUS_UPPER_STATUS BIT(18) #define TSENS_TM_SN_STATUS_LOWER_STATUS BIT(17) #define TSENS_TM_SN_LAST_TEMP_MASK 0xfff #define TSENS_TM_CODE_BIT_MASK 0xfff #define TSENS_TM_0C_THR_MASK 0xfff #define TSENS_TM_0C_THR_OFFSET 12 #define TSENS_TM_CODE_SIGN_BIT 0x800 #define TSENS_TM_SCALE_DECI_MILLIDEG 100 #define TSENS_DEBUG_WDOG_TRIGGER_COUNT 5 Loading @@ -58,6 +61,10 @@ #define TSENS_TM_TRDY(n) ((n) + 0xe4) #define TSENS_TM_TRDY_FIRST_ROUND_COMPLETE BIT(3) #define TSENS_TM_TRDY_FIRST_ROUND_COMPLETE_SHIFT 3 #define TSENS_TM_0C_INT_STATUS(n) ((n) + 0xe0) #define TSENS_TM_MIN_TEMP(n) ((n) + 0xec) #define TSENS_TM_0C_THRESHOLDS(n) ((n) + 0x1c) #define TSENS_MAX_READ_FAIL 50 static void msm_tsens_convert_temp(int last_temp, int *temp) { Loading Loading @@ -92,7 +99,7 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp) code, tmdev->trdy_fail_ctr); tmdev->trdy_fail_ctr++; if (tmdev->trdy_fail_ctr >= 50) { if (tmdev->trdy_fail_ctr >= TSENS_MAX_READ_FAIL) { if (tmdev->ops->dbg) tmdev->ops->dbg(tmdev, 0, TSENS_DBG_LOG_BUS_ID_DATA, NULL); Loading Loading @@ -147,6 +154,75 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp) return 0; } int tsens_2xxx_get_min_temp(struct tsens_sensor *sensor, int *temp) { struct tsens_device *tmdev = NULL; unsigned int code; void __iomem *sensor_addr, *trdy; int last_temp = 0, last_temp2 = 0, last_temp3 = 0, valid_bit; if (!sensor) return -EINVAL; tmdev = sensor->tmdev; trdy = TSENS_TM_TRDY(tmdev->tsens_tm_addr); valid_bit = TSENS_TM_MIN_TEMP_VALID_BIT; sensor_addr = TSENS_TM_MIN_TEMP(tmdev->tsens_tm_addr); code = readl_relaxed_no_log(trdy); if (!((code & TSENS_TM_TRDY_FIRST_ROUND_COMPLETE) >> TSENS_TM_TRDY_FIRST_ROUND_COMPLETE_SHIFT)) { pr_err("tsens device first round not complete0x%x, ctr is %d\n", code, tmdev->trdy_fail_ctr); tmdev->trdy_fail_ctr++; if (tmdev->trdy_fail_ctr >= TSENS_MAX_READ_FAIL) { if (tmdev->ops->dbg) tmdev->ops->dbg(tmdev, 0, TSENS_DBG_LOG_BUS_ID_DATA, NULL); BUG(); } return -ENODATA; } tmdev->trdy_fail_ctr = 0; code = readl_relaxed_no_log(sensor_addr); last_temp = code & TSENS_TM_SN_LAST_TEMP_MASK; if (code & valid_bit) { msm_tsens_convert_temp(last_temp, temp); goto dbg; } code = readl_relaxed_no_log(sensor_addr); last_temp2 = code & TSENS_TM_SN_LAST_TEMP_MASK; if (code & valid_bit) { last_temp = last_temp2; msm_tsens_convert_temp(last_temp, temp); goto dbg; } code = readl_relaxed_no_log(sensor_addr); last_temp3 = code & TSENS_TM_SN_LAST_TEMP_MASK; if (code & valid_bit) { last_temp = last_temp3; msm_tsens_convert_temp(last_temp, temp); goto dbg; } if (last_temp == last_temp2) last_temp = last_temp2; else if (last_temp2 == last_temp3) last_temp = last_temp3; msm_tsens_convert_temp(last_temp, temp); dbg: TSENS_DBG(tmdev, "Min temp: %d\n", *temp); return 0; } static int tsens_tm_activate_trip_type(struct tsens_sensor *tm_sensor, int trip, enum thermal_device_mode mode) { Loading Loading @@ -518,6 +594,31 @@ static irqreturn_t tsens_tm_irq_thread(int irq, void *data) return IRQ_HANDLED; } static irqreturn_t tsens_tm_0C_irq_thread(int irq, void *data) { struct tsens_device *tm = data; int status, thrs, set_thr, reset_thr; void __iomem *srot_addr, *addr; addr = TSENS_TM_0C_INT_STATUS(tm->tsens_tm_addr); status = readl_relaxed(addr); srot_addr = TSENS_CTRL_ADDR(tm->tsens_srot_addr); thrs = readl_relaxed(TSENS_TM_0C_THRESHOLDS(srot_addr)); msm_tsens_convert_temp(thrs & TSENS_TM_0C_THR_MASK, &reset_thr); msm_tsens_convert_temp( ((thrs >> TSENS_TM_0C_THR_OFFSET) & TSENS_TM_0C_THR_MASK), &set_thr); if (status) of_thermal_handle_trip_temp(tm->min_temp.tzd, set_thr); else of_thermal_handle_trip_temp(tm->min_temp.tzd, reset_thr); return IRQ_HANDLED; } static int tsens2xxx_hw_sensor_en(struct tsens_device *tmdev, u32 sensor_id) { Loading Loading @@ -602,19 +703,26 @@ static int tsens2xxx_hw_init(struct tsens_device *tmdev) static const struct tsens_irqs tsens2xxx_irqs[] = { { "tsens-upper-lower", tsens_tm_irq_thread}, { "tsens-critical", tsens_tm_critical_irq_thread}, { "tsens-0C", tsens_tm_0C_irq_thread}, }; static int tsens2xxx_register_interrupts(struct tsens_device *tmdev) { struct platform_device *pdev; int i, rc; int i, rc, irq_no; unsigned long irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; if (!tmdev) return -EINVAL; if (tmdev->min_temp_sensor_id != MIN_TEMP_DEF_OFFSET) irq_no = ARRAY_SIZE(tsens2xxx_irqs); else irq_no = ARRAY_SIZE(tsens2xxx_irqs) - 1; pdev = tmdev->pdev; for (i = 0; i < ARRAY_SIZE(tsens2xxx_irqs); i++) { for (i = 0; i < irq_no; i++) { int irq; irq = platform_get_irq_byname(pdev, tsens2xxx_irqs[i].name); Loading @@ -624,10 +732,12 @@ static int tsens2xxx_register_interrupts(struct tsens_device *tmdev) return irq; } if (i == 2) irqflags = IRQF_TRIGGER_RISING | IRQF_ONESHOT; rc = devm_request_threaded_irq(&pdev->dev, irq, NULL, tsens2xxx_irqs[i].handler, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, tsens2xxx_irqs[i].name, tmdev); irqflags, tsens2xxx_irqs[i].name, tmdev); if (rc) { dev_err(&pdev->dev, "failed to get irq %s\n", tsens2xxx_irqs[i].name); Loading Loading @@ -677,3 +787,14 @@ const struct tsens_data data_tsens24xx = { .ops = &ops_tsens2xxx, .mtc = false, }; const struct tsens_data data_tsens26xx = { .cycle_monitor = true, .cycle_compltn_monitor_mask = 1, .wd_bark = true, .wd_bark_mask = 0, .ops = &ops_tsens2xxx, .mtc = false, .ver_major = 2, .ver_minor = 6, }; Loading
drivers/thermal/msm-tsens.c +31 −0 Original line number Diff line number Diff line Loading @@ -25,6 +25,13 @@ static int tsens_get_temp(void *data, int *temp) return tmdev->ops->get_temp(s, temp); } static int tsens_get_min_temp(void *data, int *temp) { struct tsens_sensor *s = data; return tsens_2xxx_get_min_temp(s, temp); } static int tsens_set_trip_temp(void *data, int low_temp, int high_temp) { struct tsens_sensor *s = data; Loading Loading @@ -82,6 +89,9 @@ static const struct of_device_id tsens_table[] = { { .compatible = "qcom,tsens24xx", .data = &data_tsens24xx, }, { .compatible = "qcom,tsens26xx", .data = &data_tsens26xx, }, { .compatible = "qcom,msm8937-tsens", .data = &data_tsens14xx, }, Loading @@ -97,6 +107,10 @@ static struct thermal_zone_of_device_ops tsens_tm_thermal_zone_ops = { .set_trips = tsens_set_trip_temp, }; static struct thermal_zone_of_device_ops tsens_tm_min_thermal_zone_ops = { .get_temp = tsens_get_min_temp, }; static int get_device_tree_data(struct platform_device *pdev, struct tsens_device *tmdev) { Loading @@ -105,6 +119,7 @@ static int get_device_tree_data(struct platform_device *pdev, const struct tsens_data *data; int rc = 0; struct resource *res_tsens_mem; u32 min_temp_id; if (!of_match_node(tsens_table, of_node)) { pr_err("Need to read SoC specific fuse map\n"); Loading Loading @@ -179,6 +194,11 @@ static int get_device_tree_data(struct platform_device *pdev, } } if (!of_property_read_u32(of_node, "0C-sensor-num", &min_temp_id)) tmdev->min_temp_sensor_id = (int)min_temp_id; else tmdev->min_temp_sensor_id = MIN_TEMP_DEF_OFFSET; return rc; } Loading Loading @@ -209,6 +229,17 @@ static int tsens_thermal_zone_register(struct tsens_device *tmdev) return -ENODEV; } if (tmdev->min_temp_sensor_id != MIN_TEMP_DEF_OFFSET) { tmdev->min_temp.tmdev = tmdev; tmdev->min_temp.hw_id = tmdev->min_temp_sensor_id; tmdev->min_temp.tzd = devm_thermal_zone_of_sensor_register( &tmdev->pdev->dev, tmdev->min_temp_sensor_id, &tmdev->min_temp, &tsens_tm_min_thermal_zone_ops); if (IS_ERR(tmdev->min_temp.tzd)) pr_err("Error registering min temp sensor\n"); } /* Register virtual thermal sensors. */ qti_virtual_sensor_register(&tmdev->pdev->dev); Loading
drivers/thermal/tsens.h +8 −1 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ #define SLOPE_DEFAULT 3200 #define IPC_LOGPAGES 10 #define MIN_TEMP_DEF_OFFSET 0xFF enum tsens_dbg_type { TSENS_DBG_POLL, Loading Loading @@ -208,14 +209,20 @@ struct tsens_device { const struct tsens_data *ctrl_data; struct tsens_mtc_sysfs mtcsys; int trdy_fail_ctr; struct tsens_sensor min_temp; u8 min_temp_sensor_id; struct tsens_sensor sensor[0]; }; extern const struct tsens_data data_tsens2xxx, data_tsens23xx, data_tsens24xx; extern const struct tsens_data data_tsens2xxx, data_tsens23xx, data_tsens24xx, data_tsens26xx; extern const struct tsens_data data_tsens14xx, data_tsens14xx_405; extern struct list_head tsens_device_list; extern int calibrate_8937(struct tsens_device *tmdev); extern int calibrate_405(struct tsens_device *tmdev); extern int tsens_2xxx_get_min_temp( struct tsens_sensor *sensor, int *temp); #endif /* __QCOM_TSENS_H__ */
drivers/thermal/tsens2xxx.c +126 −5 Original line number Diff line number Diff line Loading @@ -42,12 +42,15 @@ #define TSENS_TM_UPPER_LOWER_INT_MASK(n) ((n) + 0x10) #define TSENS_TM_UPPER_INT_SET(n) (1 << (n + 16)) #define TSENS_TM_SN_CRITICAL_THRESHOLD_MASK 0xfff #define TSENS_TM_MIN_TEMP_VALID_BIT BIT(16) #define TSENS_TM_SN_STATUS_VALID_BIT BIT(21) #define TSENS_TM_SN_STATUS_CRITICAL_STATUS BIT(19) #define TSENS_TM_SN_STATUS_UPPER_STATUS BIT(18) #define TSENS_TM_SN_STATUS_LOWER_STATUS BIT(17) #define TSENS_TM_SN_LAST_TEMP_MASK 0xfff #define TSENS_TM_CODE_BIT_MASK 0xfff #define TSENS_TM_0C_THR_MASK 0xfff #define TSENS_TM_0C_THR_OFFSET 12 #define TSENS_TM_CODE_SIGN_BIT 0x800 #define TSENS_TM_SCALE_DECI_MILLIDEG 100 #define TSENS_DEBUG_WDOG_TRIGGER_COUNT 5 Loading @@ -58,6 +61,10 @@ #define TSENS_TM_TRDY(n) ((n) + 0xe4) #define TSENS_TM_TRDY_FIRST_ROUND_COMPLETE BIT(3) #define TSENS_TM_TRDY_FIRST_ROUND_COMPLETE_SHIFT 3 #define TSENS_TM_0C_INT_STATUS(n) ((n) + 0xe0) #define TSENS_TM_MIN_TEMP(n) ((n) + 0xec) #define TSENS_TM_0C_THRESHOLDS(n) ((n) + 0x1c) #define TSENS_MAX_READ_FAIL 50 static void msm_tsens_convert_temp(int last_temp, int *temp) { Loading Loading @@ -92,7 +99,7 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp) code, tmdev->trdy_fail_ctr); tmdev->trdy_fail_ctr++; if (tmdev->trdy_fail_ctr >= 50) { if (tmdev->trdy_fail_ctr >= TSENS_MAX_READ_FAIL) { if (tmdev->ops->dbg) tmdev->ops->dbg(tmdev, 0, TSENS_DBG_LOG_BUS_ID_DATA, NULL); Loading Loading @@ -147,6 +154,75 @@ static int tsens2xxx_get_temp(struct tsens_sensor *sensor, int *temp) return 0; } int tsens_2xxx_get_min_temp(struct tsens_sensor *sensor, int *temp) { struct tsens_device *tmdev = NULL; unsigned int code; void __iomem *sensor_addr, *trdy; int last_temp = 0, last_temp2 = 0, last_temp3 = 0, valid_bit; if (!sensor) return -EINVAL; tmdev = sensor->tmdev; trdy = TSENS_TM_TRDY(tmdev->tsens_tm_addr); valid_bit = TSENS_TM_MIN_TEMP_VALID_BIT; sensor_addr = TSENS_TM_MIN_TEMP(tmdev->tsens_tm_addr); code = readl_relaxed_no_log(trdy); if (!((code & TSENS_TM_TRDY_FIRST_ROUND_COMPLETE) >> TSENS_TM_TRDY_FIRST_ROUND_COMPLETE_SHIFT)) { pr_err("tsens device first round not complete0x%x, ctr is %d\n", code, tmdev->trdy_fail_ctr); tmdev->trdy_fail_ctr++; if (tmdev->trdy_fail_ctr >= TSENS_MAX_READ_FAIL) { if (tmdev->ops->dbg) tmdev->ops->dbg(tmdev, 0, TSENS_DBG_LOG_BUS_ID_DATA, NULL); BUG(); } return -ENODATA; } tmdev->trdy_fail_ctr = 0; code = readl_relaxed_no_log(sensor_addr); last_temp = code & TSENS_TM_SN_LAST_TEMP_MASK; if (code & valid_bit) { msm_tsens_convert_temp(last_temp, temp); goto dbg; } code = readl_relaxed_no_log(sensor_addr); last_temp2 = code & TSENS_TM_SN_LAST_TEMP_MASK; if (code & valid_bit) { last_temp = last_temp2; msm_tsens_convert_temp(last_temp, temp); goto dbg; } code = readl_relaxed_no_log(sensor_addr); last_temp3 = code & TSENS_TM_SN_LAST_TEMP_MASK; if (code & valid_bit) { last_temp = last_temp3; msm_tsens_convert_temp(last_temp, temp); goto dbg; } if (last_temp == last_temp2) last_temp = last_temp2; else if (last_temp2 == last_temp3) last_temp = last_temp3; msm_tsens_convert_temp(last_temp, temp); dbg: TSENS_DBG(tmdev, "Min temp: %d\n", *temp); return 0; } static int tsens_tm_activate_trip_type(struct tsens_sensor *tm_sensor, int trip, enum thermal_device_mode mode) { Loading Loading @@ -518,6 +594,31 @@ static irqreturn_t tsens_tm_irq_thread(int irq, void *data) return IRQ_HANDLED; } static irqreturn_t tsens_tm_0C_irq_thread(int irq, void *data) { struct tsens_device *tm = data; int status, thrs, set_thr, reset_thr; void __iomem *srot_addr, *addr; addr = TSENS_TM_0C_INT_STATUS(tm->tsens_tm_addr); status = readl_relaxed(addr); srot_addr = TSENS_CTRL_ADDR(tm->tsens_srot_addr); thrs = readl_relaxed(TSENS_TM_0C_THRESHOLDS(srot_addr)); msm_tsens_convert_temp(thrs & TSENS_TM_0C_THR_MASK, &reset_thr); msm_tsens_convert_temp( ((thrs >> TSENS_TM_0C_THR_OFFSET) & TSENS_TM_0C_THR_MASK), &set_thr); if (status) of_thermal_handle_trip_temp(tm->min_temp.tzd, set_thr); else of_thermal_handle_trip_temp(tm->min_temp.tzd, reset_thr); return IRQ_HANDLED; } static int tsens2xxx_hw_sensor_en(struct tsens_device *tmdev, u32 sensor_id) { Loading Loading @@ -602,19 +703,26 @@ static int tsens2xxx_hw_init(struct tsens_device *tmdev) static const struct tsens_irqs tsens2xxx_irqs[] = { { "tsens-upper-lower", tsens_tm_irq_thread}, { "tsens-critical", tsens_tm_critical_irq_thread}, { "tsens-0C", tsens_tm_0C_irq_thread}, }; static int tsens2xxx_register_interrupts(struct tsens_device *tmdev) { struct platform_device *pdev; int i, rc; int i, rc, irq_no; unsigned long irqflags = IRQF_TRIGGER_HIGH | IRQF_ONESHOT; if (!tmdev) return -EINVAL; if (tmdev->min_temp_sensor_id != MIN_TEMP_DEF_OFFSET) irq_no = ARRAY_SIZE(tsens2xxx_irqs); else irq_no = ARRAY_SIZE(tsens2xxx_irqs) - 1; pdev = tmdev->pdev; for (i = 0; i < ARRAY_SIZE(tsens2xxx_irqs); i++) { for (i = 0; i < irq_no; i++) { int irq; irq = platform_get_irq_byname(pdev, tsens2xxx_irqs[i].name); Loading @@ -624,10 +732,12 @@ static int tsens2xxx_register_interrupts(struct tsens_device *tmdev) return irq; } if (i == 2) irqflags = IRQF_TRIGGER_RISING | IRQF_ONESHOT; rc = devm_request_threaded_irq(&pdev->dev, irq, NULL, tsens2xxx_irqs[i].handler, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, tsens2xxx_irqs[i].name, tmdev); irqflags, tsens2xxx_irqs[i].name, tmdev); if (rc) { dev_err(&pdev->dev, "failed to get irq %s\n", tsens2xxx_irqs[i].name); Loading Loading @@ -677,3 +787,14 @@ const struct tsens_data data_tsens24xx = { .ops = &ops_tsens2xxx, .mtc = false, }; const struct tsens_data data_tsens26xx = { .cycle_monitor = true, .cycle_compltn_monitor_mask = 1, .wd_bark = true, .wd_bark_mask = 0, .ops = &ops_tsens2xxx, .mtc = false, .ver_major = 2, .ver_minor = 6, };