/* * The conversion between ADC and temperature is based on linear relationship, * and use idea_k to specify the slope and ideal_b to specify the offset. * * Since different Spreadtrum SoCs have different ideal_k and ideal_b, * we should save ideal_k and ideal_b in the device data structure.
*/ struct sprd_thm_variant_data {
u32 ideal_k;
u32 ideal_b;
};
cell = of_nvmem_cell_get(np, cell_id); if (IS_ERR(cell)) return PTR_ERR(cell);
buf = nvmem_cell_read(cell, &len);
nvmem_cell_put(cell); if (IS_ERR(buf)) return PTR_ERR(buf);
if (len > sizeof(u32)) {
kfree(buf); return -EINVAL;
}
memcpy(val, buf, len);
kfree(buf); return 0;
}
staticint sprd_thm_sensor_calibration(struct device_node *np, struct sprd_thermal_data *thm, struct sprd_thermal_sensor *sen)
{ int ret; /* * According to thermal datasheet, the default calibration offset is 64, * and the default ratio is 1000.
*/ int dt_offset = 64, ratio = 1000;
ret = sprd_thm_cal_read(np, "sen_delta_cal", &dt_offset); if (ret) return ret;
ratio += thm->ratio_sign * thm->ratio_off;
/* * According to the ideal slope K and ideal offset B, combined with * calibration value of thermal from efuse, then calibrate the real * slope k and offset b: * k_cal = (k * ratio) / 1000. * b_cal = b + (dt_offset - 64) * 500.
*/
sen->cal_slope = (thm->var_data->ideal_k * ratio) / 1000;
sen->cal_offset = thm->var_data->ideal_b + (dt_offset - 128) * 250;
/* * According to the thermal datasheet, the formula of converting * adc value to the temperature value should be: * T_final = k_cal * x - b_cal.
*/ return sen->cal_slope * rawdata - sen->cal_offset;
}
/* * According to the thermal datasheet, the formula of converting * adc value to the temperature value should be: * T_final = k_cal * x - b_cal.
*/
val = (temp + sen->cal_offset) / sen->cal_slope;
/* Wait for first temperature data ready before reading temperature */ return readl_poll_timeout(thm->base + SPRD_THM_INTERNAL_STS1, val,
!(val & SPRD_THM_TEMPER_RDY),
SPRD_THM_TEMP_READY_POLL_TIME,
SPRD_THM_TEMP_READY_TIMEOUT);
}
staticint sprd_thm_set_ready(struct sprd_thermal_data *thm)
{ int ret;
ret = sprd_thm_poll_ready_status(thm); if (ret) return ret;
/* * Clear interrupt status, enable thermal interrupt and enable thermal. * * The SPRD thermal controller integrates a hardware interrupt signal, * which means if the temperature is overheat, it will generate an * interrupt and notify the event to PMIC automatically to shutdown the * system. So here we should enable the interrupt bits, though we have * not registered an irq handler.
*/
writel(SPRD_THM_INT_CLR_MASK, thm->base + SPRD_THM_INT_CLR);
sprd_thm_update_bits(thm->base + SPRD_THM_INT_EN,
SPRD_THM_BIT_INT_EN, SPRD_THM_BIT_INT_EN);
sprd_thm_update_bits(thm->base + SPRD_THM_CTL,
SPRD_THM_EN, SPRD_THM_EN); return 0;
}
/* Enable the sensor' overheat temperature protection interrupt */
sprd_thm_update_bits(thm->base + SPRD_THM_INT_EN,
SPRD_THM_SEN_OVERHEAT_ALARM_EN(sen->id),
SPRD_THM_SEN_OVERHEAT_ALARM_EN(sen->id));
/* Set the sensor' overheat and hot threshold temperature */
sprd_thm_update_bits(thm->base + SPRD_THM_THRES(sen->id),
SPRD_THM_THRES_MASK,
(otp_rawdata << SPRD_THM_OTP_TRIP_SHIFT) |
hot_rawdata);
staticvoid sprd_thm_para_config(struct sprd_thermal_data *thm)
{ /* Set the period of two valid temperature detection action */
sprd_thm_update_bits(thm->base + SPRD_THM_DET_PERIOD,
SPRD_THM_DET_PERIOD_MASK, SPRD_THM_DET_PERIOD);
/* Set the sensors' monitor mode */
sprd_thm_update_bits(thm->base + SPRD_THM_MON_CTL,
SPRD_THM_MON_MODE_MASK, SPRD_THM_MON_MODE);
/* Set the sensors' monitor period */
sprd_thm_update_bits(thm->base + SPRD_THM_MON_PERIOD,
SPRD_THM_MON_PERIOD_MASK, SPRD_THM_MON_PERIOD);
}
staticint sprd_thm_hw_resume(struct sprd_thermal_data *thm)
{ int ret, i;
for (i = 0; i < thm->nr_sensors; i++) {
sprd_thm_update_bits(thm->base + SPRD_THM_CTL,
SPRD_THM_SEN(thm->sensor[i]->id),
SPRD_THM_SEN(thm->sensor[i]->id));
}
ret = sprd_thm_poll_ready_status(thm); if (ret) return ret;
for (i = 0; i < thm->nr_sensors; i++) {
sprd_thm_toggle_sensor(thm->sensor[i], false);
devm_thermal_of_zone_unregister(&pdev->dev,
thm->sensor[i]->tzd);
}
}
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.