Lines Matching +full:msm8916 +full:- +full:tsens
1 // SPDX-License-Identifier: GPL-2.0
11 #include <linux/nvmem-consumer.h>
22 #include "tsens.h"
25 * struct tsens_irq_data - IRQ status and temperature violations
76 * and offset values are derived from tz->tzp->slope and tz->tzp->offset
85 for (i = 0; i < priv->num_sensors; i++) { in compute_intercept_slope()
86 dev_dbg(priv->dev, in compute_intercept_slope()
87 "%s: sensor%d - data_point1:%#x data_point2:%#x\n", in compute_intercept_slope()
90 if (!priv->sensor[i].slope) in compute_intercept_slope()
91 priv->sensor[i].slope = SLOPE_DEFAULT; in compute_intercept_slope()
94 * slope (m) = adc_code2 - adc_code1 (y2 - y1)/ in compute_intercept_slope()
95 * temp_120_degc - temp_30_degc (x2 - x1) in compute_intercept_slope()
97 num = p2[i] - p1[i]; in compute_intercept_slope()
99 den = CAL_DEGC_PT2 - CAL_DEGC_PT1; in compute_intercept_slope()
100 priv->sensor[i].slope = num / den; in compute_intercept_slope()
103 priv->sensor[i].offset = (p1[i] * SLOPE_FACTOR) - in compute_intercept_slope()
105 priv->sensor[i].slope); in compute_intercept_slope()
106 dev_dbg(priv->dev, "%s: offset:%d\n", __func__, in compute_intercept_slope()
107 priv->sensor[i].offset); in compute_intercept_slope()
113 u64 code = div_u64(((u64)degc * s->slope + s->offset), SLOPE_FACTOR); in degc_to_code()
123 num = (adc_code * SLOPE_FACTOR) - s->offset; in code_to_degc()
124 den = s->slope; in code_to_degc()
129 degc = num - (den / 2); in code_to_degc()
139 * tsens_hw_to_mC - Return sign-extended temperature in mCelsius.
151 struct tsens_priv *priv = s->priv; in tsens_hw_to_mC()
156 resolution = priv->fields[LAST_TEMP_0].msb - in tsens_hw_to_mC()
157 priv->fields[LAST_TEMP_0].lsb; in tsens_hw_to_mC()
159 ret = regmap_field_read(priv->rf[field], &temp); in tsens_hw_to_mC()
164 if (priv->feat->adc) in tsens_hw_to_mC()
167 /* deciCelsius -> milliCelsius along with sign extension */ in tsens_hw_to_mC()
172 * tsens_mC_to_hw - Convert temperature to hardware register value
183 struct tsens_priv *priv = s->priv; in tsens_mC_to_hw()
186 if (priv->feat->adc) in tsens_mC_to_hw()
195 return priv->feat->ver_major; in tsens_version()
214 regmap_field_write(priv->rf[index], enable ? 0 : 1); in tsens_set_interrupt_v1()
224 * - clear the mask bit in tsens_set_interrupt_v2()
226 * - Mask further interrupts for this sensor in tsens_set_interrupt_v2()
227 * - Write 1 followed by 0 to clear the interrupt in tsens_set_interrupt_v2()
245 regmap_field_write(priv->rf[index_mask], 0); in tsens_set_interrupt_v2()
247 regmap_field_write(priv->rf[index_mask], 1); in tsens_set_interrupt_v2()
248 regmap_field_write(priv->rf[index_clear], 1); in tsens_set_interrupt_v2()
249 regmap_field_write(priv->rf[index_clear], 0); in tsens_set_interrupt_v2()
254 * tsens_set_interrupt - Set state of an interrupt
255 * @priv: Pointer to tsens controller private data
260 * Call IP-specific function to set state of an interrupt
267 dev_dbg(priv->dev, "[%u] %s: %s -> %s\n", hw_id, __func__, in tsens_set_interrupt()
277 * tsens_threshold_violated - Check if a sensor temperature violated a preset threshold
278 * @priv: Pointer to tsens controller private data
290 ret = regmap_field_read(priv->rf[UPPER_STATUS_0 + hw_id], &d->up_viol); in tsens_threshold_violated()
293 ret = regmap_field_read(priv->rf[LOWER_STATUS_0 + hw_id], &d->low_viol); in tsens_threshold_violated()
297 if (priv->feat->crit_int) { in tsens_threshold_violated()
298 ret = regmap_field_read(priv->rf[CRITICAL_STATUS_0 + hw_id], in tsens_threshold_violated()
299 &d->crit_viol); in tsens_threshold_violated()
304 if (d->up_viol || d->low_viol || d->crit_viol) in tsens_threshold_violated()
316 ret = regmap_field_read(priv->rf[UP_INT_CLEAR_0 + hw_id], &d->up_irq_clear); in tsens_read_irq_state()
319 ret = regmap_field_read(priv->rf[LOW_INT_CLEAR_0 + hw_id], &d->low_irq_clear); in tsens_read_irq_state()
323 ret = regmap_field_read(priv->rf[UP_INT_MASK_0 + hw_id], &d->up_irq_mask); in tsens_read_irq_state()
326 ret = regmap_field_read(priv->rf[LOW_INT_MASK_0 + hw_id], &d->low_irq_mask); in tsens_read_irq_state()
329 ret = regmap_field_read(priv->rf[CRIT_INT_CLEAR_0 + hw_id], in tsens_read_irq_state()
330 &d->crit_irq_clear); in tsens_read_irq_state()
333 ret = regmap_field_read(priv->rf[CRIT_INT_MASK_0 + hw_id], in tsens_read_irq_state()
334 &d->crit_irq_mask); in tsens_read_irq_state()
338 d->crit_thresh = tsens_hw_to_mC(s, CRIT_THRESH_0 + hw_id); in tsens_read_irq_state()
340 /* No mask register on older TSENS */ in tsens_read_irq_state()
341 d->up_irq_mask = 0; in tsens_read_irq_state()
342 d->low_irq_mask = 0; in tsens_read_irq_state()
343 d->crit_irq_clear = 0; in tsens_read_irq_state()
344 d->crit_irq_mask = 0; in tsens_read_irq_state()
345 d->crit_thresh = 0; in tsens_read_irq_state()
348 d->up_thresh = tsens_hw_to_mC(s, UP_THRESH_0 + hw_id); in tsens_read_irq_state()
349 d->low_thresh = tsens_hw_to_mC(s, LOW_THRESH_0 + hw_id); in tsens_read_irq_state()
351 dev_dbg(priv->dev, "[%u] %s%s: status(%u|%u|%u) | clr(%u|%u|%u) | mask(%u|%u|%u)\n", in tsens_read_irq_state()
353 (d->up_viol || d->low_viol || d->crit_viol) ? "(V)" : "", in tsens_read_irq_state()
354 d->low_viol, d->up_viol, d->crit_viol, in tsens_read_irq_state()
355 d->low_irq_clear, d->up_irq_clear, d->crit_irq_clear, in tsens_read_irq_state()
356 d->low_irq_mask, d->up_irq_mask, d->crit_irq_mask); in tsens_read_irq_state()
357 dev_dbg(priv->dev, "[%u] %s%s: thresh: (%d:%d:%d)\n", hw_id, __func__, in tsens_read_irq_state()
358 (d->up_viol || d->low_viol || d->crit_viol) ? "(V)" : "", in tsens_read_irq_state()
359 d->low_thresh, d->up_thresh, d->crit_thresh); in tsens_read_irq_state()
374 * tsens_critical_irq_thread() - Threaded handler for critical interrupts
376 * @data: tsens controller private data
380 * Clear and then re-enable the interrupt.
382 * The level-triggered interrupt might deassert if the temperature returned to
395 if (priv->feat->has_watchdog) { in tsens_critical_irq_thread()
396 ret = regmap_field_read(priv->rf[WDOG_BARK_STATUS], in tsens_critical_irq_thread()
403 regmap_field_write(priv->rf[WDOG_BARK_CLEAR], 1); in tsens_critical_irq_thread()
404 regmap_field_write(priv->rf[WDOG_BARK_CLEAR], 0); in tsens_critical_irq_thread()
405 ret = regmap_field_read(priv->rf[WDOG_BARK_COUNT], in tsens_critical_irq_thread()
410 dev_dbg(priv->dev, "%s: watchdog count: %d\n", in tsens_critical_irq_thread()
417 for (i = 0; i < priv->num_sensors; i++) { in tsens_critical_irq_thread()
418 const struct tsens_sensor *s = &priv->sensor[i]; in tsens_critical_irq_thread()
419 u32 hw_id = s->hw_id; in tsens_critical_irq_thread()
421 if (!s->tzd) in tsens_critical_irq_thread()
427 dev_err(priv->dev, "[%u] %s: error reading sensor\n", in tsens_critical_irq_thread()
444 * tsens_irq_thread - Threaded interrupt handler for uplow interrupts
446 * @data: tsens controller private data
450 * update the thresholds, else re-enable the interrupts.
452 * The level-triggered interrupt might deassert if the temperature returned to
466 for (i = 0; i < priv->num_sensors; i++) { in tsens_irq_thread()
468 const struct tsens_sensor *s = &priv->sensor[i]; in tsens_irq_thread()
469 u32 hw_id = s->hw_id; in tsens_irq_thread()
471 if (!s->tzd) in tsens_irq_thread()
477 dev_err(priv->dev, "[%u] %s: error reading sensor\n", in tsens_irq_thread()
482 spin_lock_irqsave(&priv->ul_lock, flags); in tsens_irq_thread()
490 dev_dbg(priv->dev, "[%u] %s: re-arm upper\n", in tsens_irq_thread()
501 dev_dbg(priv->dev, "[%u] %s: re-arm low\n", in tsens_irq_thread()
510 spin_unlock_irqrestore(&priv->ul_lock, flags); in tsens_irq_thread()
513 dev_dbg(priv->dev, "[%u] %s: TZ update trigger (%d mC)\n", in tsens_irq_thread()
515 thermal_zone_device_update(s->tzd, in tsens_irq_thread()
518 dev_dbg(priv->dev, "[%u] %s: no violation: %d\n", in tsens_irq_thread()
537 struct tsens_sensor *s = tz->devdata; in tsens_set_trips()
538 struct tsens_priv *priv = s->priv; in tsens_set_trips()
539 struct device *dev = priv->dev; in tsens_set_trips()
543 u32 hw_id = s->hw_id; in tsens_set_trips()
555 cl_high = clamp_val(high, -40000, 120000); in tsens_set_trips()
556 cl_low = clamp_val(low, -40000, 120000); in tsens_set_trips()
561 spin_lock_irqsave(&priv->ul_lock, flags); in tsens_set_trips()
566 regmap_field_write(priv->rf[LOW_THRESH_0 + hw_id], low_val); in tsens_set_trips()
567 regmap_field_write(priv->rf[UP_THRESH_0 + hw_id], high_val); in tsens_set_trips()
571 spin_unlock_irqrestore(&priv->ul_lock, flags); in tsens_set_trips()
573 dev_dbg(dev, "[%u] %s: (%d:%d)->(%d:%d)\n", in tsens_set_trips()
584 ret = regmap_field_write(priv->rf[INT_EN], val); in tsens_enable_irq()
586 dev_err(priv->dev, "%s: failed to enable interrupts\n", in tsens_enable_irq()
594 regmap_field_write(priv->rf[INT_EN], 0); in tsens_disable_irq()
599 struct tsens_priv *priv = s->priv; in get_temp_tsens_valid()
600 int hw_id = s->hw_id; in get_temp_tsens_valid()
616 ret = regmap_field_read_poll_timeout(priv->rf[valid_idx], valid, in get_temp_tsens_valid()
630 struct tsens_priv *priv = s->priv; in get_temp_common()
631 int hw_id = s->hw_id; in get_temp_common()
638 ret = regmap_field_read(priv->rf[TRDY], &trdy); in get_temp_common()
645 ret = regmap_field_read(priv->rf[LAST_TEMP_0 + hw_id], &last_temp); in get_temp_common()
654 return -ETIMEDOUT; in get_temp_common()
660 struct platform_device *pdev = s->private; in dbg_sensors_show()
665 priv->feat->max_sensors, priv->num_sensors); in dbg_sensors_show()
667 seq_puts(s, " id slope offset\n--------------------------\n"); in dbg_sensors_show()
668 for (i = 0; i < priv->num_sensors; i++) { in dbg_sensors_show()
669 seq_printf(s, "%8d %8d %8d\n", priv->sensor[i].hw_id, in dbg_sensors_show()
670 priv->sensor[i].slope, priv->sensor[i].offset); in dbg_sensors_show()
678 struct platform_device *pdev = s->private; in dbg_version_show()
684 ret = regmap_field_read(priv->rf[VER_MAJOR], &maj_ver); in dbg_version_show()
687 ret = regmap_field_read(priv->rf[VER_MINOR], &min_ver); in dbg_version_show()
690 ret = regmap_field_read(priv->rf[VER_STEP], &step_ver); in dbg_version_show()
709 root = debugfs_lookup("tsens", NULL); in tsens_debug_init()
711 priv->debug_root = debugfs_create_dir("tsens", NULL); in tsens_debug_init()
713 priv->debug_root = root; in tsens_debug_init()
715 file = debugfs_lookup("version", priv->debug_root); in tsens_debug_init()
717 debugfs_create_file("version", 0444, priv->debug_root, in tsens_debug_init()
720 /* A directory for each instance of the TSENS IP */ in tsens_debug_init()
721 priv->debug = debugfs_create_dir(dev_name(&pdev->dev), priv->debug_root); in tsens_debug_init()
722 debugfs_create_file("sensors", 0444, priv->debug, pdev, &dbg_sensors_fops); in tsens_debug_init()
745 struct device *dev = priv->dev; in init_common()
750 struct platform_device *op = of_find_device_by_node(priv->dev->of_node); in init_common()
753 return -EINVAL; in init_common()
755 if (op->num_resources > 1) { in init_common()
757 priv->tm_offset = 0; in init_common()
765 priv->srot_map = devm_regmap_init_mmio(dev, srot_base, in init_common()
767 if (IS_ERR(priv->srot_map)) { in init_common()
768 ret = PTR_ERR(priv->srot_map); in init_common()
773 priv->tm_offset = 0x1000; in init_common()
784 priv->tm_map = devm_regmap_init_mmio(dev, tm_base, &tsens_config); in init_common()
786 struct device *parent = priv->dev->parent; in init_common()
789 priv->tm_map = syscon_node_to_regmap(parent->of_node); in init_common()
792 if (IS_ERR_OR_NULL(priv->tm_map)) { in init_common()
793 if (!priv->tm_map) in init_common()
794 ret = -ENODEV; in init_common()
796 ret = PTR_ERR(priv->tm_map); in init_common()
801 if (!priv->srot_map) in init_common()
802 priv->srot_map = priv->tm_map; in init_common()
806 priv->rf[i] = devm_regmap_field_alloc(dev, priv->srot_map, in init_common()
807 priv->fields[i]); in init_common()
808 if (IS_ERR(priv->rf[i])) { in init_common()
809 ret = PTR_ERR(priv->rf[i]); in init_common()
813 ret = regmap_field_read(priv->rf[VER_MINOR], &ver_minor); in init_common()
818 priv->rf[TSENS_EN] = devm_regmap_field_alloc(dev, priv->srot_map, in init_common()
819 priv->fields[TSENS_EN]); in init_common()
820 if (IS_ERR(priv->rf[TSENS_EN])) { in init_common()
821 ret = PTR_ERR(priv->rf[TSENS_EN]); in init_common()
824 /* in VER_0 TSENS need to be explicitly enabled */ in init_common()
826 regmap_field_write(priv->rf[TSENS_EN], 1); in init_common()
828 ret = regmap_field_read(priv->rf[TSENS_EN], &enabled); in init_common()
833 ret = -ENODEV; in init_common()
837 priv->rf[SENSOR_EN] = devm_regmap_field_alloc(dev, priv->srot_map, in init_common()
838 priv->fields[SENSOR_EN]); in init_common()
839 if (IS_ERR(priv->rf[SENSOR_EN])) { in init_common()
840 ret = PTR_ERR(priv->rf[SENSOR_EN]); in init_common()
843 priv->rf[INT_EN] = devm_regmap_field_alloc(dev, priv->tm_map, in init_common()
844 priv->fields[INT_EN]); in init_common()
845 if (IS_ERR(priv->rf[INT_EN])) { in init_common()
846 ret = PTR_ERR(priv->rf[INT_EN]); in init_common()
850 priv->rf[TSENS_SW_RST] = in init_common()
851 devm_regmap_field_alloc(dev, priv->srot_map, priv->fields[TSENS_SW_RST]); in init_common()
852 if (IS_ERR(priv->rf[TSENS_SW_RST])) { in init_common()
853 ret = PTR_ERR(priv->rf[TSENS_SW_RST]); in init_common()
857 priv->rf[TRDY] = devm_regmap_field_alloc(dev, priv->tm_map, priv->fields[TRDY]); in init_common()
858 if (IS_ERR(priv->rf[TRDY])) { in init_common()
859 ret = PTR_ERR(priv->rf[TRDY]); in init_common()
865 for (i = 0; i < priv->feat->max_sensors; i++) { in init_common()
868 priv->rf[idx] = devm_regmap_field_alloc(dev, in init_common()
869 priv->tm_map, in init_common()
870 priv->fields[idx]); in init_common()
871 if (IS_ERR(priv->rf[idx])) { in init_common()
872 ret = PTR_ERR(priv->rf[idx]); in init_common()
878 if (priv->feat->crit_int || tsens_version(priv) < VER_0_1) { in init_common()
881 for (i = 0; i < priv->feat->max_sensors; i++) { in init_common()
884 priv->rf[idx] = in init_common()
886 priv->tm_map, in init_common()
887 priv->fields[idx]); in init_common()
888 if (IS_ERR(priv->rf[idx])) { in init_common()
889 ret = PTR_ERR(priv->rf[idx]); in init_common()
898 priv->feat->has_watchdog = 1; in init_common()
900 priv->rf[i] = devm_regmap_field_alloc(dev, priv->tm_map, in init_common()
901 priv->fields[i]); in init_common()
902 if (IS_ERR(priv->rf[i])) { in init_common()
903 ret = PTR_ERR(priv->rf[i]); in init_common()
911 regmap_field_write(priv->rf[WDOG_BARK_MASK], 0); in init_common()
912 regmap_field_write(priv->rf[CC_MON_MASK], 1); in init_common()
915 spin_lock_init(&priv->ul_lock); in init_common()
924 put_device(&op->dev); in init_common()
930 struct tsens_sensor *s = tz->devdata; in tsens_get_temp()
931 struct tsens_priv *priv = s->priv; in tsens_get_temp()
933 return priv->ops->get_temp(s, temp); in tsens_get_temp()
940 if (priv->ops && priv->ops->suspend) in tsens_suspend()
941 return priv->ops->suspend(priv); in tsens_suspend()
950 if (priv->ops && priv->ops->resume) in tsens_resume()
951 return priv->ops->resume(priv); in tsens_resume()
960 .compatible = "qcom,ipq8064-tsens",
963 .compatible = "qcom,mdm9607-tsens",
966 .compatible = "qcom,msm8916-tsens",
969 .compatible = "qcom,msm8939-tsens",
972 .compatible = "qcom,msm8960-tsens",
975 .compatible = "qcom,msm8974-tsens",
978 .compatible = "qcom,msm8976-tsens",
981 .compatible = "qcom,msm8996-tsens",
984 .compatible = "qcom,tsens-v1",
987 .compatible = "qcom,tsens-v2",
1005 pdev = of_find_device_by_node(priv->dev->of_node); in tsens_register_irq()
1007 return -ENODEV; in tsens_register_irq()
1013 if (irq == -ENXIO) in tsens_register_irq()
1018 ret = devm_request_threaded_irq(&pdev->dev, irq, in tsens_register_irq()
1021 dev_name(&pdev->dev), in tsens_register_irq()
1024 ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, in tsens_register_irq()
1026 dev_name(&pdev->dev), in tsens_register_irq()
1030 dev_err(&pdev->dev, "%s: failed to get irq\n", in tsens_register_irq()
1036 put_device(&pdev->dev); in tsens_register_irq()
1045 for (i = 0; i < priv->num_sensors; i++) { in tsens_register()
1046 priv->sensor[i].priv = priv; in tsens_register()
1047 tzd = devm_thermal_of_zone_register(priv->dev, priv->sensor[i].hw_id, in tsens_register()
1048 &priv->sensor[i], in tsens_register()
1052 priv->sensor[i].tzd = tzd; in tsens_register()
1053 if (priv->ops->enable) in tsens_register()
1054 priv->ops->enable(priv, i); in tsens_register()
1057 dev_warn(priv->dev, in tsens_register()
1063 * - CRIT_THRESH_0 for MAX THRESH hardcoded to 120°C in tsens_register()
1064 * - CRIT_THRESH_1 for MIN THRESH hardcoded to 0°C in tsens_register()
1067 regmap_field_write(priv->rf[CRIT_THRESH_0], in tsens_register()
1068 tsens_mC_to_hw(priv->sensor, 120000)); in tsens_register()
1070 regmap_field_write(priv->rf[CRIT_THRESH_1], in tsens_register()
1071 tsens_mC_to_hw(priv->sensor, 0)); in tsens_register()
1078 if (priv->feat->crit_int) in tsens_register()
1095 if (pdev->dev.of_node) in tsens_probe()
1096 dev = &pdev->dev; in tsens_probe()
1098 dev = pdev->dev.parent; in tsens_probe()
1100 np = dev->of_node; in tsens_probe()
1104 data = id->data; in tsens_probe()
1108 num_sensors = data->num_sensors; in tsens_probe()
1115 return -EINVAL; in tsens_probe()
1122 return -ENOMEM; in tsens_probe()
1124 priv->dev = dev; in tsens_probe()
1125 priv->num_sensors = num_sensors; in tsens_probe()
1126 priv->ops = data->ops; in tsens_probe()
1127 for (i = 0; i < priv->num_sensors; i++) { in tsens_probe()
1128 if (data->hw_ids) in tsens_probe()
1129 priv->sensor[i].hw_id = data->hw_ids[i]; in tsens_probe()
1131 priv->sensor[i].hw_id = i; in tsens_probe()
1133 priv->feat = data->feat; in tsens_probe()
1134 priv->fields = data->fields; in tsens_probe()
1138 if (!priv->ops || !priv->ops->init || !priv->ops->get_temp) in tsens_probe()
1139 return -EINVAL; in tsens_probe()
1141 ret = priv->ops->init(priv); in tsens_probe()
1147 if (priv->ops->calibrate) { in tsens_probe()
1148 ret = priv->ops->calibrate(priv); in tsens_probe()
1150 if (ret != -EPROBE_DEFER) in tsens_probe()
1163 debugfs_remove_recursive(priv->debug_root); in tsens_remove()
1165 if (priv->ops->disable) in tsens_remove()
1166 priv->ops->disable(priv); in tsens_remove()
1175 .name = "qcom-tsens",
1184 MODULE_ALIAS("platform:qcom-tsens");