// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2011-2015, 2017, 2020, The Linux Foundation. All rights reserved. * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
*/
#define TEMP_THRESH_STEP 5000 /* Threshold step: 5 C */
#define THRESH_MIN 0 #define THRESH_MAX 3
#define TEMP_STAGE_HYSTERESIS 2000
/* * For TEMP_GEN2 v2.0, TEMP_DAC_STG1/2/3 registers are used to set the threshold * for each stage independently. * TEMP_DAC_STG* = 0 --> 80 C * Each 8 step increase in TEMP_DAC_STG* value corresponds to 5 C (5000 mC).
*/ #define TEMP_DAC_MIN 80000 #define TEMP_DAC_SCALE_NUM 8 #define TEMP_DAC_SCALE_DEN 5000
/** * qpnp_tm_decode_temp() - return temperature in mC corresponding to the * specified over-temperature stage * @chip: Pointer to the qpnp_tm chip * @stage: Over-temperature stage * * Return: temperature in mC
*/ staticlong qpnp_tm_decode_temp(struct qpnp_tm_chip *chip, unsignedint stage)
{ if (stage == 0 || stage > STAGE_COUNT) return 0;
return chip->temp_thresh_map[stage - 1];
}
/** * qpnp_tm_gen1_get_temp_stage() - return over-temperature stage * @chip: Pointer to the qpnp_tm chip * * Return: stage on success, or errno on failure.
*/ staticint qpnp_tm_gen1_get_temp_stage(struct qpnp_tm_chip *chip)
{ int ret;
u8 reg;
ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, ®); if (ret < 0) return ret;
return FIELD_GET(STATUS_GEN1_STAGE_MASK, reg);
}
/** * qpnp_tm_gen2_get_temp_stage() - return over-temperature stage * @chip: Pointer to the qpnp_tm chip * * Return: stage on success, or errno on failure.
*/ staticint qpnp_tm_gen2_get_temp_stage(struct qpnp_tm_chip *chip)
{ int ret;
u8 reg;
ret = qpnp_tm_read(chip, QPNP_TM_REG_STATUS, ®); if (ret < 0) return ret;
ret = FIELD_GET(STATUS_GEN2_STATE_MASK, reg);
return alarm_state_map[ret];
}
/** * qpnp_tm_lite_get_temp_stage() - return over-temperature stage * @chip: Pointer to the qpnp_tm chip * * Return: alarm interrupt state on success, or errno on failure.
*/ staticint qpnp_tm_lite_get_temp_stage(struct qpnp_tm_chip *chip)
{
u8 reg = 0; int ret;
ret = qpnp_tm_read(chip, QPNP_TM_REG_IRQ_STATUS, ®); if (ret < 0) return ret;
return FIELD_GET(IRQ_STATUS_MASK, reg);
}
/* * This function updates the internal temp value based on the * current thermal stage and threshold as well as the previous stage
*/ staticint qpnp_tm_update_temp_no_adc(struct qpnp_tm_chip *chip)
{ unsignedint stage_new, stage_old; int ret;
WARN_ON(!mutex_is_locked(&chip->lock));
ret = chip->data->get_temp_stage(chip); if (ret < 0) return ret;
stage_new = ret;
stage_old = chip->stage;
if (chip->adc)
disable_stage2_shutdown = true; else
dev_warn(chip->dev, "No ADC is configured and critical temperature %d mC is above the maximum stage 2 threshold of %ld mC! Configuring stage 2 shutdown at %ld mC.\n",
temp, stage2_threshold_max, stage2_threshold_max);
}
switch (trip) { case 0:
temp_map = temp_lite_warning_map;
addr = QPNP_TM_REG_LITE_TEMP_CFG1; break; case 1: /* * The second trip point is purely in software to facilitate * a controlled shutdown after the warning threshold is crossed * but before the automatic hardware shutdown threshold is * crossed.
*/ return 0; case 2:
temp_map = temp_lite_shutdown_map;
addr = QPNP_TM_REG_LITE_TEMP_CFG2; break; default: return 0;
}
/* * Store the warning trip temp in temp_thresh_map[0] and the shutdown trip * temp in temp_thresh_map[2]. The second trip point is purely in software * to facilitate a controlled shutdown after the warning threshold is * crossed but before the automatic hardware shutdown threshold is * crossed. Thus, there is no register to read for the second trip * point.
*/
ret = qpnp_tm_read(chip, QPNP_TM_REG_LITE_TEMP_CFG1, ®); if (ret < 0) return ret;
/* * This function initializes the internal temp value based on only the * current thermal stage and threshold.
*/ staticint qpnp_tm_threshold_init(struct qpnp_tm_chip *chip)
{ int ret;
ret = chip->data->sync_thresholds(chip); if (ret < 0) return ret;
ret = chip->data->get_temp_stage(chip); if (ret < 0) return ret;
chip->stage = ret;
chip->temp = DEFAULT_TEMP;
if (chip->stage)
chip->temp = qpnp_tm_decode_temp(chip, chip->stage);
return ret;
}
/* This function initializes threshold control and disables shutdown override. */ staticint qpnp_tm_init(struct qpnp_tm_chip *chip)
{ int ret;
u8 reg;
ret = chip->data->configure_trip_temps(chip); if (ret < 0) return ret;
/* Enable the thermal alarm PMIC module in always-on mode. */
reg = ALARM_CTRL_FORCE_ENABLE;
ret = qpnp_tm_write(chip, QPNP_TM_REG_ALARM_CTRL, reg);
if (chip->subtype == QPNP_TM_SUBTYPE_GEN2) {
dig_revision = (dig_major << 8) | dig_minor; /* * Check if stage 2 automatic partial shutdown must remain * enabled to avoid potential repeated faults upon reaching * over-temperature stage 3.
*/ switch (dig_revision) { case 0x0001: case 0x0002: case 0x0100: case 0x0101:
chip->require_stage2_shutdown = true; break;
}
}
ret = qpnp_tm_threshold_init(chip); if (ret < 0) return dev_err_probe(&pdev->dev, ret, "threshold init failed\n");
/* * Register the sensor before initializing the hardware to be able to * read the trip points. get_temp() returns the default temperature * before the hardware initialization is completed.
*/
chip->tz_dev = devm_thermal_of_zone_register(
&pdev->dev, 0, chip, chip->data->ops); if (IS_ERR(chip->tz_dev)) return dev_err_probe(&pdev->dev, PTR_ERR(chip->tz_dev), "failed to register sensor\n");
ret = qpnp_tm_init(chip); if (ret < 0) return dev_err_probe(&pdev->dev, ret, "init failed\n");
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.