^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright (c) 2015, The Linux Foundation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2019, 2020, Linaro Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/debugfs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/nvmem-consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/pm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/thermal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include "tsens.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * struct tsens_irq_data - IRQ status and temperature violations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * @up_viol: upper threshold violated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * @up_thresh: upper threshold temperature value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * @up_irq_mask: mask register for upper threshold irqs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * @up_irq_clear: clear register for uppper threshold irqs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * @low_viol: lower threshold violated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * @low_thresh: lower threshold temperature value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * @low_irq_mask: mask register for lower threshold irqs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * @low_irq_clear: clear register for lower threshold irqs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * @crit_viol: critical threshold violated
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * @crit_thresh: critical threshold temperature value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * @crit_irq_mask: mask register for critical threshold irqs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) * @crit_irq_clear: clear register for critical threshold irqs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * Structure containing data about temperature threshold settings and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * irq status if they were violated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) struct tsens_irq_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) u32 up_viol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) int up_thresh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) u32 up_irq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) u32 up_irq_clear;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) u32 low_viol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) int low_thresh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) u32 low_irq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) u32 low_irq_clear;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) u32 crit_viol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) u32 crit_thresh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) u32 crit_irq_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) u32 crit_irq_clear;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) char *qfprom_read(struct device *dev, const char *cname)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct nvmem_cell *cell;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) ssize_t data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) char *ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) cell = nvmem_cell_get(dev, cname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (IS_ERR(cell))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) return ERR_CAST(cell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) ret = nvmem_cell_read(cell, &data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) nvmem_cell_put(cell);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * Use this function on devices where slope and offset calculations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * depend on calibration data read from qfprom. On others the slope
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * and offset values are derived from tz->tzp->slope and tz->tzp->offset
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * resp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) void compute_intercept_slope(struct tsens_priv *priv, u32 *p1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) u32 *p2, u32 mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) int num, den;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) for (i = 0; i < priv->num_sensors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) dev_dbg(priv->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) "%s: sensor%d - data_point1:%#x data_point2:%#x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) __func__, i, p1[i], p2[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) priv->sensor[i].slope = SLOPE_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) if (mode == TWO_PT_CALIB) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * slope (m) = adc_code2 - adc_code1 (y2 - y1)/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * temp_120_degc - temp_30_degc (x2 - x1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) num = p2[i] - p1[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) num *= SLOPE_FACTOR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) den = CAL_DEGC_PT2 - CAL_DEGC_PT1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) priv->sensor[i].slope = num / den;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) priv->sensor[i].offset = (p1[i] * SLOPE_FACTOR) -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) (CAL_DEGC_PT1 *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) priv->sensor[i].slope);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) dev_dbg(priv->dev, "%s: offset:%d\n", __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) priv->sensor[i].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) static inline u32 degc_to_code(int degc, const struct tsens_sensor *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) u64 code = div_u64(((u64)degc * s->slope + s->offset), SLOPE_FACTOR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) pr_debug("%s: raw_code: 0x%llx, degc:%d\n", __func__, code, degc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) return clamp_val(code, THRESHOLD_MIN_ADC_CODE, THRESHOLD_MAX_ADC_CODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static inline int code_to_degc(u32 adc_code, const struct tsens_sensor *s)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int degc, num, den;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) num = (adc_code * SLOPE_FACTOR) - s->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) den = s->slope;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (num > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) degc = num + (den / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) else if (num < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) degc = num - (den / 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) degc = num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) degc /= den;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return degc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * tsens_hw_to_mC - Return sign-extended temperature in mCelsius.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * @s: Pointer to sensor struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * @field: Index into regmap_field array pointing to temperature data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * This function handles temperature returned in ADC code or deciCelsius
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * depending on IP version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) * Return: Temperature in milliCelsius on success, a negative errno will
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) * be returned in error cases
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) static int tsens_hw_to_mC(const struct tsens_sensor *s, int field)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) struct tsens_priv *priv = s->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) u32 resolution;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) u32 temp = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) resolution = priv->fields[LAST_TEMP_0].msb -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) priv->fields[LAST_TEMP_0].lsb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) ret = regmap_field_read(priv->rf[field], &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) /* Convert temperature from ADC code to milliCelsius */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (priv->feat->adc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return code_to_degc(temp, s) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) /* deciCelsius -> milliCelsius along with sign extension */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) return sign_extend32(temp, resolution) * 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) * tsens_mC_to_hw - Convert temperature to hardware register value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * @s: Pointer to sensor struct
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * @temp: temperature in milliCelsius to be programmed to hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * This function outputs the value to be written to hardware in ADC code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * or deciCelsius depending on IP version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) * Return: ADC code or temperature in deciCelsius.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) static int tsens_mC_to_hw(const struct tsens_sensor *s, int temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) struct tsens_priv *priv = s->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) /* milliC to adc code */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) if (priv->feat->adc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) return degc_to_code(temp / 1000, s);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* milliC to deciC */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) return temp / 100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static inline enum tsens_ver tsens_version(struct tsens_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return priv->feat->ver_major;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static void tsens_set_interrupt_v1(struct tsens_priv *priv, u32 hw_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) enum tsens_irq_type irq_type, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) u32 index = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) switch (irq_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) case UPPER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) index = UP_INT_CLEAR_0 + hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) case LOWER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) index = LOW_INT_CLEAR_0 + hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) case CRITICAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /* No critical interrupts before v2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) regmap_field_write(priv->rf[index], enable ? 0 : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) static void tsens_set_interrupt_v2(struct tsens_priv *priv, u32 hw_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) enum tsens_irq_type irq_type, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) u32 index_mask = 0, index_clear = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) * To enable the interrupt flag for a sensor:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) * - clear the mask bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) * To disable the interrupt flag for a sensor:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) * - Mask further interrupts for this sensor
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * - Write 1 followed by 0 to clear the interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) switch (irq_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) case UPPER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) index_mask = UP_INT_MASK_0 + hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) index_clear = UP_INT_CLEAR_0 + hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) case LOWER:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) index_mask = LOW_INT_MASK_0 + hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) index_clear = LOW_INT_CLEAR_0 + hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) case CRITICAL:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) index_mask = CRIT_INT_MASK_0 + hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) index_clear = CRIT_INT_CLEAR_0 + hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) if (enable) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) regmap_field_write(priv->rf[index_mask], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) regmap_field_write(priv->rf[index_mask], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) regmap_field_write(priv->rf[index_clear], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) regmap_field_write(priv->rf[index_clear], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * tsens_set_interrupt - Set state of an interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) * @priv: Pointer to tsens controller private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) * @hw_id: Hardware ID aka. sensor number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) * @irq_type: irq_type from enum tsens_irq_type
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) * @enable: false = disable, true = enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) * Call IP-specific function to set state of an interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) * Return: void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) static void tsens_set_interrupt(struct tsens_priv *priv, u32 hw_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) enum tsens_irq_type irq_type, bool enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) dev_dbg(priv->dev, "[%u] %s: %s -> %s\n", hw_id, __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) irq_type ? ((irq_type == 1) ? "UP" : "CRITICAL") : "LOW",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) enable ? "en" : "dis");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) if (tsens_version(priv) > VER_1_X)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) tsens_set_interrupt_v2(priv, hw_id, irq_type, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) tsens_set_interrupt_v1(priv, hw_id, irq_type, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) * tsens_threshold_violated - Check if a sensor temperature violated a preset threshold
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) * @priv: Pointer to tsens controller private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) * @hw_id: Hardware ID aka. sensor number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) * @d: Pointer to irq state data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) * Return: 0 if threshold was not violated, 1 if it was violated and negative
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) * errno in case of errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) static int tsens_threshold_violated(struct tsens_priv *priv, u32 hw_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) struct tsens_irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) ret = regmap_field_read(priv->rf[UPPER_STATUS_0 + hw_id], &d->up_viol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) ret = regmap_field_read(priv->rf[LOWER_STATUS_0 + hw_id], &d->low_viol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (priv->feat->crit_int) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) ret = regmap_field_read(priv->rf[CRITICAL_STATUS_0 + hw_id],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) &d->crit_viol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) if (d->up_viol || d->low_viol || d->crit_viol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) static int tsens_read_irq_state(struct tsens_priv *priv, u32 hw_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) const struct tsens_sensor *s,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) struct tsens_irq_data *d)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) ret = regmap_field_read(priv->rf[UP_INT_CLEAR_0 + hw_id], &d->up_irq_clear);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) ret = regmap_field_read(priv->rf[LOW_INT_CLEAR_0 + hw_id], &d->low_irq_clear);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (tsens_version(priv) > VER_1_X) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) ret = regmap_field_read(priv->rf[UP_INT_MASK_0 + hw_id], &d->up_irq_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) ret = regmap_field_read(priv->rf[LOW_INT_MASK_0 + hw_id], &d->low_irq_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) ret = regmap_field_read(priv->rf[CRIT_INT_CLEAR_0 + hw_id],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) &d->crit_irq_clear);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) ret = regmap_field_read(priv->rf[CRIT_INT_MASK_0 + hw_id],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) &d->crit_irq_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) d->crit_thresh = tsens_hw_to_mC(s, CRIT_THRESH_0 + hw_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) /* No mask register on older TSENS */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) d->up_irq_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) d->low_irq_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) d->crit_irq_clear = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) d->crit_irq_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) d->crit_thresh = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) d->up_thresh = tsens_hw_to_mC(s, UP_THRESH_0 + hw_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) d->low_thresh = tsens_hw_to_mC(s, LOW_THRESH_0 + hw_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) dev_dbg(priv->dev, "[%u] %s%s: status(%u|%u|%u) | clr(%u|%u|%u) | mask(%u|%u|%u)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) hw_id, __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) (d->up_viol || d->low_viol || d->crit_viol) ? "(V)" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) d->low_viol, d->up_viol, d->crit_viol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) d->low_irq_clear, d->up_irq_clear, d->crit_irq_clear,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) d->low_irq_mask, d->up_irq_mask, d->crit_irq_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) dev_dbg(priv->dev, "[%u] %s%s: thresh: (%d:%d:%d)\n", hw_id, __func__,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) (d->up_viol || d->low_viol || d->crit_viol) ? "(V)" : "",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) d->low_thresh, d->up_thresh, d->crit_thresh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) static inline u32 masked_irq(u32 hw_id, u32 mask, enum tsens_ver ver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (ver > VER_1_X)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return mask & (1 << hw_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) /* v1, v0.1 don't have a irq mask register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) * tsens_critical_irq_thread() - Threaded handler for critical interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) * @irq: irq number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) * @data: tsens controller private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) * Check FSM watchdog bark status and clear if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) * Check all sensors to find ones that violated their critical threshold limits.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * Clear and then re-enable the interrupt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * The level-triggered interrupt might deassert if the temperature returned to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * within the threshold limits by the time the handler got scheduled. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) * consider the irq to have been handled in that case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * Return: IRQ_HANDLED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) static irqreturn_t tsens_critical_irq_thread(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) struct tsens_priv *priv = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) struct tsens_irq_data d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) int temp, ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) u32 wdog_status, wdog_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (priv->feat->has_watchdog) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) ret = regmap_field_read(priv->rf[WDOG_BARK_STATUS],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) &wdog_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (wdog_status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) /* Clear WDOG interrupt */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) regmap_field_write(priv->rf[WDOG_BARK_CLEAR], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) regmap_field_write(priv->rf[WDOG_BARK_CLEAR], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) ret = regmap_field_read(priv->rf[WDOG_BARK_COUNT],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) &wdog_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (wdog_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) dev_dbg(priv->dev, "%s: watchdog count: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) __func__, wdog_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) /* Fall through to handle critical interrupts if any */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) for (i = 0; i < priv->num_sensors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) const struct tsens_sensor *s = &priv->sensor[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) u32 hw_id = s->hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) if (!s->tzd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) if (!tsens_threshold_violated(priv, hw_id, &d))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) ret = get_temp_tsens_valid(s, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) dev_err(priv->dev, "[%u] %s: error reading sensor\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) hw_id, __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) tsens_read_irq_state(priv, hw_id, s, &d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) if (d.crit_viol &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) !masked_irq(hw_id, d.crit_irq_mask, tsens_version(priv))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) /* Mask critical interrupts, unused on Linux */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) tsens_set_interrupt(priv, hw_id, CRITICAL, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * tsens_irq_thread - Threaded interrupt handler for uplow interrupts
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) * @irq: irq number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) * @data: tsens controller private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) * Check all sensors to find ones that violated their threshold limits. If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) * temperature is still outside the limits, call thermal_zone_device_update() to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) * update the thresholds, else re-enable the interrupts.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) * The level-triggered interrupt might deassert if the temperature returned to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * within the threshold limits by the time the handler got scheduled. We
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) * consider the irq to have been handled in that case.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) * Return: IRQ_HANDLED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) static irqreturn_t tsens_irq_thread(int irq, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct tsens_priv *priv = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) struct tsens_irq_data d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) bool enable = true, disable = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) int temp, ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) for (i = 0; i < priv->num_sensors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) bool trigger = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) const struct tsens_sensor *s = &priv->sensor[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) u32 hw_id = s->hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) if (!s->tzd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) if (!tsens_threshold_violated(priv, hw_id, &d))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) ret = get_temp_tsens_valid(s, &temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) dev_err(priv->dev, "[%u] %s: error reading sensor\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) hw_id, __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) spin_lock_irqsave(&priv->ul_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) tsens_read_irq_state(priv, hw_id, s, &d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) if (d.up_viol &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) !masked_irq(hw_id, d.up_irq_mask, tsens_version(priv))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) tsens_set_interrupt(priv, hw_id, UPPER, disable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) if (d.up_thresh > temp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) dev_dbg(priv->dev, "[%u] %s: re-arm upper\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) hw_id, __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) tsens_set_interrupt(priv, hw_id, UPPER, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) trigger = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) /* Keep irq masked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) } else if (d.low_viol &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) !masked_irq(hw_id, d.low_irq_mask, tsens_version(priv))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) tsens_set_interrupt(priv, hw_id, LOWER, disable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) if (d.low_thresh < temp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) dev_dbg(priv->dev, "[%u] %s: re-arm low\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) hw_id, __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) tsens_set_interrupt(priv, hw_id, LOWER, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) trigger = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) /* Keep irq masked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) spin_unlock_irqrestore(&priv->ul_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) if (trigger) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) dev_dbg(priv->dev, "[%u] %s: TZ update trigger (%d mC)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) hw_id, __func__, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) thermal_zone_device_update(s->tzd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) THERMAL_EVENT_UNSPECIFIED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) dev_dbg(priv->dev, "[%u] %s: no violation: %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) hw_id, __func__, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) static int tsens_set_trips(void *_sensor, int low, int high)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) struct tsens_sensor *s = _sensor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) struct tsens_priv *priv = s->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) struct device *dev = priv->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) struct tsens_irq_data d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) unsigned long flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) int high_val, low_val, cl_high, cl_low;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) u32 hw_id = s->hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) dev_dbg(dev, "[%u] %s: proposed thresholds: (%d:%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) hw_id, __func__, low, high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) cl_high = clamp_val(high, -40000, 120000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) cl_low = clamp_val(low, -40000, 120000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) high_val = tsens_mC_to_hw(s, cl_high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) low_val = tsens_mC_to_hw(s, cl_low);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) spin_lock_irqsave(&priv->ul_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) tsens_read_irq_state(priv, hw_id, s, &d);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) /* Write the new thresholds and clear the status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) regmap_field_write(priv->rf[LOW_THRESH_0 + hw_id], low_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) regmap_field_write(priv->rf[UP_THRESH_0 + hw_id], high_val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) tsens_set_interrupt(priv, hw_id, LOWER, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) tsens_set_interrupt(priv, hw_id, UPPER, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) spin_unlock_irqrestore(&priv->ul_lock, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) dev_dbg(dev, "[%u] %s: (%d:%d)->(%d:%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) hw_id, __func__, d.low_thresh, d.up_thresh, cl_low, cl_high);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) static int tsens_enable_irq(struct tsens_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) int val = tsens_version(priv) > VER_1_X ? 7 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) ret = regmap_field_write(priv->rf[INT_EN], val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) dev_err(priv->dev, "%s: failed to enable interrupts\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) static void tsens_disable_irq(struct tsens_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) regmap_field_write(priv->rf[INT_EN], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) int get_temp_tsens_valid(const struct tsens_sensor *s, int *temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) struct tsens_priv *priv = s->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) int hw_id = s->hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) u32 temp_idx = LAST_TEMP_0 + hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) u32 valid_idx = VALID_0 + hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) u32 valid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) ret = regmap_field_read(priv->rf[valid_idx], &valid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) while (!valid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) /* Valid bit is 0 for 6 AHB clock cycles.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * At 19.2MHz, 1 AHB clock is ~60ns.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * We should enter this loop very, very rarely.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) ndelay(400);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) ret = regmap_field_read(priv->rf[valid_idx], &valid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* Valid bit is set, OK to read the temperature */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) *temp = tsens_hw_to_mC(s, temp_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) int get_temp_common(const struct tsens_sensor *s, int *temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) struct tsens_priv *priv = s->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) int hw_id = s->hw_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) int last_temp = 0, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) ret = regmap_field_read(priv->rf[LAST_TEMP_0 + hw_id], &last_temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) *temp = code_to_degc(last_temp, s) * 1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) #ifdef CONFIG_DEBUG_FS
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) static int dbg_sensors_show(struct seq_file *s, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) struct platform_device *pdev = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) struct tsens_priv *priv = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) seq_printf(s, "max: %2d\nnum: %2d\n\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) priv->feat->max_sensors, priv->num_sensors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) seq_puts(s, " id slope offset\n--------------------------\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) for (i = 0; i < priv->num_sensors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) seq_printf(s, "%8d %8d %8d\n", priv->sensor[i].hw_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) priv->sensor[i].slope, priv->sensor[i].offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) static int dbg_version_show(struct seq_file *s, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct platform_device *pdev = s->private;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) struct tsens_priv *priv = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) u32 maj_ver, min_ver, step_ver;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) if (tsens_version(priv) > VER_0_1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) ret = regmap_field_read(priv->rf[VER_MAJOR], &maj_ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) ret = regmap_field_read(priv->rf[VER_MINOR], &min_ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) ret = regmap_field_read(priv->rf[VER_STEP], &step_ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) seq_printf(s, "%d.%d.%d\n", maj_ver, min_ver, step_ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) seq_puts(s, "0.1.0\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) DEFINE_SHOW_ATTRIBUTE(dbg_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) DEFINE_SHOW_ATTRIBUTE(dbg_sensors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) static void tsens_debug_init(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) struct tsens_priv *priv = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) struct dentry *root, *file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) root = debugfs_lookup("tsens", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) if (!root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) priv->debug_root = debugfs_create_dir("tsens", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) priv->debug_root = root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) file = debugfs_lookup("version", priv->debug_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) if (!file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) debugfs_create_file("version", 0444, priv->debug_root,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) pdev, &dbg_version_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) /* A directory for each instance of the TSENS IP */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) priv->debug = debugfs_create_dir(dev_name(&pdev->dev), priv->debug_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) debugfs_create_file("sensors", 0444, priv->debug, pdev, &dbg_sensors_fops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) static inline void tsens_debug_init(struct platform_device *pdev) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) static const struct regmap_config tsens_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) .name = "tm",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) .reg_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) .val_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) .reg_stride = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static const struct regmap_config tsens_srot_config = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) .name = "srot",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) .reg_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) .val_bits = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) .reg_stride = 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) int __init init_common(struct tsens_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) void __iomem *tm_base, *srot_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct device *dev = priv->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) u32 ver_minor;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) u32 enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) int ret, i, j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) struct platform_device *op = of_find_device_by_node(priv->dev->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) if (!op)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (op->num_resources > 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) /* DT with separate SROT and TM address space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) priv->tm_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) res = platform_get_resource(op, IORESOURCE_MEM, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) srot_base = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) if (IS_ERR(srot_base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) ret = PTR_ERR(srot_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) goto err_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) priv->srot_map = devm_regmap_init_mmio(dev, srot_base,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) &tsens_srot_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) if (IS_ERR(priv->srot_map)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) ret = PTR_ERR(priv->srot_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) goto err_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) /* old DTs where SROT and TM were in a contiguous 2K block */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) priv->tm_offset = 0x1000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) res = platform_get_resource(op, IORESOURCE_MEM, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) tm_base = devm_ioremap_resource(dev, res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) if (IS_ERR(tm_base)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) ret = PTR_ERR(tm_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) goto err_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) priv->tm_map = devm_regmap_init_mmio(dev, tm_base, &tsens_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (IS_ERR(priv->tm_map)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) ret = PTR_ERR(priv->tm_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) goto err_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) if (tsens_version(priv) > VER_0_1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) for (i = VER_MAJOR; i <= VER_STEP; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) priv->rf[i] = devm_regmap_field_alloc(dev, priv->srot_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) priv->fields[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (IS_ERR(priv->rf[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) ret = PTR_ERR(priv->rf[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) goto err_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) ret = regmap_field_read(priv->rf[VER_MINOR], &ver_minor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) goto err_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) priv->rf[TSENS_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) priv->fields[TSENS_EN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) if (IS_ERR(priv->rf[TSENS_EN])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) ret = PTR_ERR(priv->rf[TSENS_EN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) goto err_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) ret = regmap_field_read(priv->rf[TSENS_EN], &enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) goto err_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) if (!enabled) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) dev_err(dev, "%s: device not enabled\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) ret = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) goto err_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) priv->rf[SENSOR_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) priv->fields[SENSOR_EN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (IS_ERR(priv->rf[SENSOR_EN])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) ret = PTR_ERR(priv->rf[SENSOR_EN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) goto err_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) priv->rf[INT_EN] = devm_regmap_field_alloc(dev, priv->tm_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) priv->fields[INT_EN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) if (IS_ERR(priv->rf[INT_EN])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) ret = PTR_ERR(priv->rf[INT_EN]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) goto err_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) /* This loop might need changes if enum regfield_ids is reordered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) for (j = LAST_TEMP_0; j <= UP_THRESH_15; j += 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) for (i = 0; i < priv->feat->max_sensors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) int idx = j + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) priv->rf[idx] = devm_regmap_field_alloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) priv->tm_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) priv->fields[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (IS_ERR(priv->rf[idx])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) ret = PTR_ERR(priv->rf[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) goto err_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (priv->feat->crit_int) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) /* Loop might need changes if enum regfield_ids is reordered */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) for (j = CRITICAL_STATUS_0; j <= CRIT_THRESH_15; j += 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) for (i = 0; i < priv->feat->max_sensors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) int idx = j + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) priv->rf[idx] =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) devm_regmap_field_alloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) priv->tm_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) priv->fields[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (IS_ERR(priv->rf[idx])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) ret = PTR_ERR(priv->rf[idx]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) goto err_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (tsens_version(priv) > VER_1_X && ver_minor > 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) /* Watchdog is present only on v2.3+ */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) priv->feat->has_watchdog = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) for (i = WDOG_BARK_STATUS; i <= CC_MON_MASK; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) priv->rf[i] = devm_regmap_field_alloc(dev, priv->tm_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) priv->fields[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (IS_ERR(priv->rf[i])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) ret = PTR_ERR(priv->rf[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) goto err_put_device;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) * Watchdog is already enabled, unmask the bark.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) * Disable cycle completion monitoring
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) regmap_field_write(priv->rf[WDOG_BARK_MASK], 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) regmap_field_write(priv->rf[CC_MON_MASK], 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) spin_lock_init(&priv->ul_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) tsens_enable_irq(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) tsens_debug_init(op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) err_put_device:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) put_device(&op->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) static int tsens_get_temp(void *data, int *temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) struct tsens_sensor *s = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) struct tsens_priv *priv = s->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) return priv->ops->get_temp(s, temp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) static int tsens_get_trend(void *data, int trip, enum thermal_trend *trend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) struct tsens_sensor *s = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct tsens_priv *priv = s->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) if (priv->ops->get_trend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) return priv->ops->get_trend(s, trend);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) static int __maybe_unused tsens_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) struct tsens_priv *priv = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (priv->ops && priv->ops->suspend)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) return priv->ops->suspend(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) static int __maybe_unused tsens_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) struct tsens_priv *priv = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) if (priv->ops && priv->ops->resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) return priv->ops->resume(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) static SIMPLE_DEV_PM_OPS(tsens_pm_ops, tsens_suspend, tsens_resume);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) static const struct of_device_id tsens_table[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) .compatible = "qcom,msm8916-tsens",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) .data = &data_8916,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) .compatible = "qcom,msm8939-tsens",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) .data = &data_8939,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) .compatible = "qcom,msm8974-tsens",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) .data = &data_8974,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) .compatible = "qcom,msm8976-tsens",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) .data = &data_8976,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) .compatible = "qcom,msm8996-tsens",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) .data = &data_8996,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) .compatible = "qcom,tsens-v1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) .data = &data_tsens_v1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) .compatible = "qcom,tsens-v2",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) .data = &data_tsens_v2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) {}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) MODULE_DEVICE_TABLE(of, tsens_table);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) static const struct thermal_zone_of_device_ops tsens_of_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) .get_temp = tsens_get_temp,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) .get_trend = tsens_get_trend,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) .set_trips = tsens_set_trips,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) static int tsens_register_irq(struct tsens_priv *priv, char *irqname,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) irq_handler_t thread_fn)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) struct platform_device *pdev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) int ret, irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) pdev = of_find_device_by_node(priv->dev->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) if (!pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) irq = platform_get_irq_byname(pdev, irqname);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (irq < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) ret = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) /* For old DTs with no IRQ defined */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) if (irq == -ENXIO)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) ret = devm_request_threaded_irq(&pdev->dev, irq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) NULL, thread_fn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) IRQF_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) dev_name(&pdev->dev), priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) dev_err(&pdev->dev, "%s: failed to get irq\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) enable_irq_wake(irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) put_device(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) static int tsens_register(struct tsens_priv *priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) int i, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) struct thermal_zone_device *tzd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) for (i = 0; i < priv->num_sensors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) priv->sensor[i].priv = priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) tzd = devm_thermal_zone_of_sensor_register(priv->dev, priv->sensor[i].hw_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) &priv->sensor[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) &tsens_of_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (IS_ERR(tzd))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) priv->sensor[i].tzd = tzd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if (priv->ops->enable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) priv->ops->enable(priv, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) ret = tsens_register_irq(priv, "uplow", tsens_irq_thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (priv->feat->crit_int)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) ret = tsens_register_irq(priv, "critical",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) tsens_critical_irq_thread);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) static int tsens_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) int ret, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) struct device_node *np;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) struct tsens_priv *priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) const struct tsens_plat_data *data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) const struct of_device_id *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) u32 num_sensors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) if (pdev->dev.of_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) dev = pdev->dev.parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) id = of_match_node(tsens_table, np);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) data = id->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) data = &data_8960;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) num_sensors = data->num_sensors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) of_property_read_u32(np, "#qcom,sensors", &num_sensors);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) if (num_sensors <= 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) dev_err(dev, "%s: invalid number of sensors\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) priv = devm_kzalloc(dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) struct_size(priv, sensor, num_sensors),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (!priv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) priv->dev = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) priv->num_sensors = num_sensors;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) priv->ops = data->ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) for (i = 0; i < priv->num_sensors; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) if (data->hw_ids)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) priv->sensor[i].hw_id = data->hw_ids[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) priv->sensor[i].hw_id = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) priv->feat = data->feat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) priv->fields = data->fields;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) platform_set_drvdata(pdev, priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) if (!priv->ops || !priv->ops->init || !priv->ops->get_temp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) ret = priv->ops->init(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) dev_err(dev, "%s: init failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) if (priv->ops->calibrate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) ret = priv->ops->calibrate(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) if (ret != -EPROBE_DEFER)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) dev_err(dev, "%s: calibration failed\n", __func__);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) return tsens_register(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) static int tsens_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) struct tsens_priv *priv = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) debugfs_remove_recursive(priv->debug_root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) tsens_disable_irq(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (priv->ops->disable)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) priv->ops->disable(priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) static struct platform_driver tsens_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) .probe = tsens_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) .remove = tsens_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) .name = "qcom-tsens",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) .pm = &tsens_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) .of_match_table = tsens_table,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) module_platform_driver(tsens_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) MODULE_DESCRIPTION("QCOM Temperature Sensor driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) MODULE_ALIAS("platform:qcom-tsens");