in tegra/tegra30-tsensor.c [429:507]
static int tegra_tsensor_nvmem_setup(struct tegra_tsensor *ts)
{
u32 i, ate_ver = 0, cal = 0, t1_25C = 0, t2_90C = 0;
int err, c1_25C, c2_90C;
err = tegra_fuse_readl(TEGRA30_FUSE_TEST_PROG_VER, &ate_ver);
if (err) {
dev_err_probe(ts->dev, err, "failed to get ATE version\n");
return err;
}
if (ate_ver < 8) {
dev_info(ts->dev, "unsupported ATE version: %u\n", ate_ver);
return -ENODEV;
}
/*
* We have two TSENSOR channels in a two different spots on SoC.
* Second channel provides more accurate data on older SoC versions,
* use it as a primary channel.
*/
if (ate_ver <= 21) {
dev_info_once(ts->dev,
"older ATE version detected, channels remapped\n");
ts->swap_channels = true;
}
err = tegra_fuse_readl(TEGRA30_FUSE_TSENSOR_CALIB, &cal);
if (err) {
dev_err(ts->dev, "failed to get calibration data: %d\n", err);
return err;
}
/* get calibrated counter values for 25C/90C thresholds */
c1_25C = FIELD_GET(TEGRA30_FUSE_TSENSOR_CALIB_LOW, cal);
c2_90C = FIELD_GET(TEGRA30_FUSE_TSENSOR_CALIB_HIGH, cal);
/* and calibrated temperatures corresponding to the counter values */
for (i = 0; i < 7; i++) {
t1_25C |= tegra_tsensor_fuse_read_spare(14 + i) << i;
t1_25C |= tegra_tsensor_fuse_read_spare(21 + i) << i;
t2_90C |= tegra_tsensor_fuse_read_spare(0 + i) << i;
t2_90C |= tegra_tsensor_fuse_read_spare(7 + i) << i;
}
if (c2_90C - c1_25C <= t2_90C - t1_25C) {
dev_err(ts->dev, "invalid calibration data: %d %d %u %u\n",
c2_90C, c1_25C, t2_90C, t1_25C);
return -EINVAL;
}
/* all calibration coefficients are premultiplied by 1000000 */
ts->calib.a = DIV_ROUND_CLOSEST((t2_90C - t1_25C) * 1000000,
(c2_90C - c1_25C));
ts->calib.b = t1_25C * 1000000 - ts->calib.a * c1_25C;
if (tegra_sku_info.revision == TEGRA_REVISION_A01) {
ts->calib.m = -2775;
ts->calib.n = 1338811;
ts->calib.p = -7300000;
} else {
ts->calib.m = -3512;
ts->calib.n = 1528943;
ts->calib.p = -11100000;
}
/* except the coefficient of a reduced quadratic equation */
ts->calib.r = DIV_ROUND_CLOSEST(ts->calib.n, ts->calib.m * 2);
dev_info_once(ts->dev,
"calibration: %d %d %u %u ATE ver: %u SoC rev: %u\n",
c2_90C, c1_25C, t2_90C, t1_25C, ate_ver,
tegra_sku_info.revision);
return 0;
}