/* * The MT8173 thermal controller has four banks. Each bank can read up to * four temperature sensors simultaneously. The MT8173 has a total of 5 * temperature sensors. We use each bank to measure a certain area of the * SoC. Since TS2 is located centrally in the SoC it is influenced by multiple * areas, hence is used in different banks. * * The thermal core only gets the maximum temperature of all banks, so * the bank concept wouldn't be necessary here. However, the SVS (Smart * Voltage Scaling) unit makes its decisions based on the same bank * data, and this indeed needs the temperatures of the individual banks * for making better decisions.
*/ staticconststruct mtk_thermal_data mt8173_thermal_data = {
.auxadc_channel = MT8173_TEMP_AUXADC_CHANNEL,
.num_banks = MT8173_NUM_ZONES,
.num_sensors = MT8173_NUM_SENSORS,
.vts_index = mt8173_vts_index,
.cali_val = MT8173_CALIBRATION,
.num_controller = MT8173_NUM_CONTROLLER,
.controller_offset = mt8173_tc_offset,
.need_switch_bank = true,
.bank_data = {
{
.num_sensors = 2,
.sensors = mt8173_bank_data[0],
}, {
.num_sensors = 2,
.sensors = mt8173_bank_data[1],
}, {
.num_sensors = 3,
.sensors = mt8173_bank_data[2],
}, {
.num_sensors = 1,
.sensors = mt8173_bank_data[3],
},
},
.msr = mt8173_msr,
.adcpnp = mt8173_adcpnp,
.sensor_mux_values = mt8173_mux_values,
.version = MTK_THERMAL_V1,
};
/* * The MT2701 thermal controller has one bank, which can read up to * three temperature sensors simultaneously. The MT2701 has a total of 3 * temperature sensors. * * The thermal core only gets the maximum temperature of this one bank, * so the bank concept wouldn't be necessary here. However, the SVS (Smart * Voltage Scaling) unit makes its decisions based on the same bank * data.
*/ staticconststruct mtk_thermal_data mt2701_thermal_data = {
.auxadc_channel = MT2701_TEMP_AUXADC_CHANNEL,
.num_banks = 1,
.num_sensors = MT2701_NUM_SENSORS,
.vts_index = mt2701_vts_index,
.cali_val = MT2701_CALIBRATION,
.num_controller = MT2701_NUM_CONTROLLER,
.controller_offset = mt2701_tc_offset,
.need_switch_bank = true,
.bank_data = {
{
.num_sensors = 3,
.sensors = mt2701_bank_data,
},
},
.msr = mt2701_msr,
.adcpnp = mt2701_adcpnp,
.sensor_mux_values = mt2701_mux_values,
.version = MTK_THERMAL_V1,
};
/* * The MT8365 thermal controller has one bank, which can read up to * four temperature sensors simultaneously. The MT8365 has a total of 3 * temperature sensors. * * The thermal core only gets the maximum temperature of this one bank, * so the bank concept wouldn't be necessary here. However, the SVS (Smart * Voltage Scaling) unit makes its decisions based on the same bank * data.
*/ staticconststruct mtk_thermal_data mt8365_thermal_data = {
.auxadc_channel = MT8365_TEMP_AUXADC_CHANNEL,
.num_banks = MT8365_NUM_BANKS,
.num_sensors = MT8365_NUM_SENSORS,
.vts_index = mt8365_vts_index,
.cali_val = MT8365_CALIBRATION,
.num_controller = MT8365_NUM_CONTROLLER,
.controller_offset = mt8365_tc_offset,
.need_switch_bank = false,
.bank_data = {
{
.num_sensors = MT8365_NUM_SENSORS,
.sensors = mt8365_bank_data
},
},
.msr = mt8365_msr,
.adcpnp = mt8365_adcpnp,
.sensor_mux_values = mt8365_mux_values,
.version = MTK_THERMAL_V1,
.apmixed_buffer_ctl_reg = APMIXED_SYS_TS_CON0,
.apmixed_buffer_ctl_mask = (u32) ~GENMASK(29, 28),
.apmixed_buffer_ctl_set = 0,
};
/* * The MT2712 thermal controller has one bank, which can read up to * four temperature sensors simultaneously. The MT2712 has a total of 4 * temperature sensors. * * The thermal core only gets the maximum temperature of this one bank, * so the bank concept wouldn't be necessary here. However, the SVS (Smart * Voltage Scaling) unit makes its decisions based on the same bank * data.
*/ staticconststruct mtk_thermal_data mt2712_thermal_data = {
.auxadc_channel = MT2712_TEMP_AUXADC_CHANNEL,
.num_banks = 1,
.num_sensors = MT2712_NUM_SENSORS,
.vts_index = mt2712_vts_index,
.cali_val = MT2712_CALIBRATION,
.num_controller = MT2712_NUM_CONTROLLER,
.controller_offset = mt2712_tc_offset,
.need_switch_bank = true,
.bank_data = {
{
.num_sensors = 4,
.sensors = mt2712_bank_data,
},
},
.msr = mt2712_msr,
.adcpnp = mt2712_adcpnp,
.sensor_mux_values = mt2712_mux_values,
.version = MTK_THERMAL_V1,
};
/* * The MT8183 thermal controller has one bank for the current SW framework. * The MT8183 has a total of 6 temperature sensors. * There are two thermal controller to control the six sensor. * The first one bind 2 sensor, and the other bind 4 sensors. * The thermal core only gets the maximum temperature of all sensor, so * the bank concept wouldn't be necessary here. However, the SVS (Smart * Voltage Scaling) unit makes its decisions based on the same bank * data, and this indeed needs the temperatures of the individual banks * for making better decisions.
*/ staticconststruct mtk_thermal_data mt8183_thermal_data = {
.auxadc_channel = MT8183_TEMP_AUXADC_CHANNEL,
.num_banks = MT8183_NUM_ZONES,
.num_sensors = MT8183_NUM_SENSORS,
.vts_index = mt8183_vts_index,
.cali_val = MT8183_CALIBRATION,
.num_controller = MT8183_NUM_CONTROLLER,
.controller_offset = mt8183_tc_offset,
.need_switch_bank = false,
.bank_data = {
{
.num_sensors = 6,
.sensors = mt8183_bank_data,
},
},
/** * raw_to_mcelsius_v1 - convert a raw ADC value to mcelsius * @mt: The thermal controller * @sensno: sensor number * @raw: raw ADC value * * This converts the raw ADC value to mcelsius using the SoC specific * calibration constants
*/ staticint raw_to_mcelsius_v1(struct mtk_thermal *mt, int sensno, s32 raw)
{
s32 tmp;
/** * mtk_thermal_get_bank - get bank * @bank: The bank * * The bank registers are banked, we have to select a bank in the * PTPCORESEL register to access it.
*/ staticvoid mtk_thermal_get_bank(struct mtk_thermal_bank *bank)
{ struct mtk_thermal *mt = bank->mt;
u32 val;
if (mt->conf->need_switch_bank) {
mutex_lock(&mt->lock);
val = readl(mt->thermal_base + PTPCORESEL);
val &= ~0xf;
val |= bank->id;
writel(val, mt->thermal_base + PTPCORESEL);
}
}
/** * mtk_thermal_put_bank - release bank * @bank: The bank * * release a bank previously taken with mtk_thermal_get_bank,
*/ staticvoid mtk_thermal_put_bank(struct mtk_thermal_bank *bank)
{ struct mtk_thermal *mt = bank->mt;
if (mt->conf->need_switch_bank)
mutex_unlock(&mt->lock);
}
/** * mtk_thermal_bank_temperature - get the temperature of a bank * @bank: The bank * * The temperature of a bank is considered the maximum temperature of * the sensors associated to the bank.
*/ staticint mtk_thermal_bank_temperature(struct mtk_thermal_bank *bank)
{ struct mtk_thermal *mt = bank->mt; conststruct mtk_thermal_data *conf = mt->conf; int i, temp = INT_MIN, max = INT_MIN;
u32 raw;
for (i = 0; i < conf->bank_data[bank->id].num_sensors; i++) {
raw = readl(mt->thermal_base + conf->msr[i]);
/* * Depending on the filt/sen intervals and ADC polling time, * we may need up to 60 milliseconds after initialization: this * will result in the first reading containing an out of range * temperature value. * Validate the reading to both address the aforementioned issue * and to eventually avoid bogus readings during runtime in the * event that the AUXADC gets unstable due to high EMI, etc.
*/ if (!mtk_thermal_temp_is_valid(temp))
temp = THERMAL_TEMP_INVALID;
if (temp > max)
max = temp;
}
return max;
}
staticint mtk_read_temp(struct thermal_zone_device *tz, int *temperature)
{ struct mtk_thermal *mt = thermal_zone_device_priv(tz); int i; int tempmax = INT_MIN;
for (i = 0; i < mt->conf->num_banks; i++) { struct mtk_thermal_bank *bank = &mt->banks[i];
/* exceed this polling time, IRQ would be inserted */
writel(0xffffffff, controller_base + TEMP_AHBTO);
/* number of interrupts per event, 1 is enough */
writel(0x0, controller_base + TEMP_MONIDET0);
writel(0x0, controller_base + TEMP_MONIDET1);
/* * The MT8173 thermal controller does not have its own ADC. Instead it * uses AHB bus accesses to control the AUXADC. To do this the thermal * controller has to be programmed with the physical addresses of the * AUXADC registers and with the various bit positions in the AUXADC. * Also the thermal controller controls a mux in the APMIXEDSYS register * space.
*/
/* * this value will be stored to TEMP_PNPMUXADDR (TEMP_SPARE0) * automatically by hw
*/
writel(BIT(conf->auxadc_channel), controller_base + TEMP_ADCMUX);
for (i = 0; i < conf->bank_data[num].num_sensors; i++)
writel(conf->sensor_mux_values[conf->bank_data[num].sensors[i]],
mt->thermal_base + conf->adcpnp[i]);
if (CALIB_BUF1_ID_V3(buf[1]) == 0)
mt->o_slope = 0;
return 0;
}
staticint mtk_thermal_get_calibration_data(struct device *dev, struct mtk_thermal *mt)
{ struct nvmem_cell *cell;
u32 *buf;
size_t len; int i, ret = 0;
/* Start with default values */
mt->adc_ge = 512;
mt->adc_oe = 512; for (i = 0; i < mt->conf->num_sensors; i++)
mt->vts[i] = 260;
mt->degc_cali = 40;
mt->o_slope = 0;
cell = nvmem_cell_get(dev, "calibration-data"); if (IS_ERR(cell)) { if (PTR_ERR(cell) == -EPROBE_DEFER) return PTR_ERR(cell); return 0;
}
buf = (u32 *)nvmem_cell_read(cell, &len);
nvmem_cell_put(cell);
if (IS_ERR(buf)) return PTR_ERR(buf);
if (len < 3 * sizeof(u32)) {
dev_warn(dev, "invalid calibration data\n");
ret = -EINVAL; goto out;
}
switch (mt->conf->version) { case MTK_THERMAL_V1:
ret = mtk_thermal_extract_efuse_v1(mt, buf); break; case MTK_THERMAL_V2:
ret = mtk_thermal_extract_efuse_v2(mt, buf); break; case MTK_THERMAL_V3:
ret = mtk_thermal_extract_efuse_v3(mt, buf); break; default:
ret = -EINVAL; break;
}
if (ret) {
dev_info(dev, "Device not calibrated, using default calibration values\n");
ret = 0;
}
for (ctrl_id = 0; ctrl_id < mt->conf->num_controller ; ctrl_id++) for (i = 0; i < mt->conf->num_banks; i++)
mtk_thermal_init_bank(mt, i, apmixed_phys_base,
auxadc_phys_base, ctrl_id);
tzdev = devm_thermal_of_zone_register(&pdev->dev, 0, mt,
&mtk_thermal_ops); if (IS_ERR(tzdev)) return PTR_ERR(tzdev);
ret = devm_thermal_add_hwmon_sysfs(&pdev->dev, tzdev); if (ret)
dev_warn(&pdev->dev, "error in thermal_add_hwmon_sysfs");
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.