|
@@ -118,12 +118,12 @@ struct rockchip_tsadc_chip {
|
|
void (*control)(void __iomem *reg, bool on);
|
|
void (*control)(void __iomem *reg, bool on);
|
|
|
|
|
|
/* Per-sensor methods */
|
|
/* Per-sensor methods */
|
|
- int (*get_temp)(struct chip_tsadc_table table,
|
|
|
|
|
|
+ int (*get_temp)(const struct chip_tsadc_table *table,
|
|
int chn, void __iomem *reg, int *temp);
|
|
int chn, void __iomem *reg, int *temp);
|
|
- void (*set_alarm_temp)(struct chip_tsadc_table table,
|
|
|
|
- int chn, void __iomem *reg, int temp);
|
|
|
|
- void (*set_tshut_temp)(struct chip_tsadc_table table,
|
|
|
|
- int chn, void __iomem *reg, int temp);
|
|
|
|
|
|
+ int (*set_alarm_temp)(const struct chip_tsadc_table *table,
|
|
|
|
+ int chn, void __iomem *reg, int temp);
|
|
|
|
+ int (*set_tshut_temp)(const struct chip_tsadc_table *table,
|
|
|
|
+ int chn, void __iomem *reg, int temp);
|
|
void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
|
|
void (*set_tshut_mode)(int chn, void __iomem *reg, enum tshut_mode m);
|
|
|
|
|
|
/* Per-table methods */
|
|
/* Per-table methods */
|
|
@@ -317,6 +317,7 @@ static const struct tsadc_table rk3288_code_table[] = {
|
|
{3452, 115000},
|
|
{3452, 115000},
|
|
{3437, 120000},
|
|
{3437, 120000},
|
|
{3421, 125000},
|
|
{3421, 125000},
|
|
|
|
+ {0, 125000},
|
|
};
|
|
};
|
|
|
|
|
|
static const struct tsadc_table rk3368_code_table[] = {
|
|
static const struct tsadc_table rk3368_code_table[] = {
|
|
@@ -397,59 +398,80 @@ static const struct tsadc_table rk3399_code_table[] = {
|
|
{TSADCV3_DATA_MASK, 125000},
|
|
{TSADCV3_DATA_MASK, 125000},
|
|
};
|
|
};
|
|
|
|
|
|
-static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table,
|
|
|
|
|
|
+static u32 rk_tsadcv2_temp_to_code(const struct chip_tsadc_table *table,
|
|
int temp)
|
|
int temp)
|
|
{
|
|
{
|
|
int high, low, mid;
|
|
int high, low, mid;
|
|
- u32 error = 0;
|
|
|
|
|
|
+ unsigned long num;
|
|
|
|
+ unsigned int denom;
|
|
|
|
+ u32 error = table->data_mask;
|
|
|
|
|
|
low = 0;
|
|
low = 0;
|
|
- high = table.length - 1;
|
|
|
|
|
|
+ high = (table->length - 1) - 1; /* ignore the last check for table */
|
|
mid = (high + low) / 2;
|
|
mid = (high + low) / 2;
|
|
|
|
|
|
/* Return mask code data when the temp is over table range */
|
|
/* Return mask code data when the temp is over table range */
|
|
- if (temp < table.id[low].temp || temp > table.id[high].temp) {
|
|
|
|
- error = table.data_mask;
|
|
|
|
|
|
+ if (temp < table->id[low].temp || temp > table->id[high].temp)
|
|
goto exit;
|
|
goto exit;
|
|
- }
|
|
|
|
|
|
|
|
while (low <= high) {
|
|
while (low <= high) {
|
|
- if (temp == table.id[mid].temp)
|
|
|
|
- return table.id[mid].code;
|
|
|
|
- else if (temp < table.id[mid].temp)
|
|
|
|
|
|
+ if (temp == table->id[mid].temp)
|
|
|
|
+ return table->id[mid].code;
|
|
|
|
+ else if (temp < table->id[mid].temp)
|
|
high = mid - 1;
|
|
high = mid - 1;
|
|
else
|
|
else
|
|
low = mid + 1;
|
|
low = mid + 1;
|
|
mid = (low + high) / 2;
|
|
mid = (low + high) / 2;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /*
|
|
|
|
+ * The conversion code granularity provided by the table. Let's
|
|
|
|
+ * assume that the relationship between temperature and
|
|
|
|
+ * analog value between 2 table entries is linear and interpolate
|
|
|
|
+ * to produce less granular result.
|
|
|
|
+ */
|
|
|
|
+ num = abs(table->id[mid + 1].code - table->id[mid].code);
|
|
|
|
+ num *= temp - table->id[mid].temp;
|
|
|
|
+ denom = table->id[mid + 1].temp - table->id[mid].temp;
|
|
|
|
+
|
|
|
|
+ switch (table->mode) {
|
|
|
|
+ case ADC_DECREMENT:
|
|
|
|
+ return table->id[mid].code - (num / denom);
|
|
|
|
+ case ADC_INCREMENT:
|
|
|
|
+ return table->id[mid].code + (num / denom);
|
|
|
|
+ default:
|
|
|
|
+ pr_err("%s: unknown table mode: %d\n", __func__, table->mode);
|
|
|
|
+ return error;
|
|
|
|
+ }
|
|
|
|
+
|
|
exit:
|
|
exit:
|
|
- pr_err("Invalid the conversion, error=%d\n", error);
|
|
|
|
|
|
+ pr_err("%s: invalid temperature, temp=%d error=%d\n",
|
|
|
|
+ __func__, temp, error);
|
|
return error;
|
|
return error;
|
|
}
|
|
}
|
|
|
|
|
|
-static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code,
|
|
|
|
- int *temp)
|
|
|
|
|
|
+static int rk_tsadcv2_code_to_temp(const struct chip_tsadc_table *table,
|
|
|
|
+ u32 code, int *temp)
|
|
{
|
|
{
|
|
unsigned int low = 1;
|
|
unsigned int low = 1;
|
|
- unsigned int high = table.length - 1;
|
|
|
|
|
|
+ unsigned int high = table->length - 1;
|
|
unsigned int mid = (low + high) / 2;
|
|
unsigned int mid = (low + high) / 2;
|
|
unsigned int num;
|
|
unsigned int num;
|
|
unsigned long denom;
|
|
unsigned long denom;
|
|
|
|
|
|
- WARN_ON(table.length < 2);
|
|
|
|
|
|
+ WARN_ON(table->length < 2);
|
|
|
|
|
|
- switch (table.mode) {
|
|
|
|
|
|
+ switch (table->mode) {
|
|
case ADC_DECREMENT:
|
|
case ADC_DECREMENT:
|
|
- code &= table.data_mask;
|
|
|
|
- if (code < table.id[high].code)
|
|
|
|
|
|
+ code &= table->data_mask;
|
|
|
|
+ if (code <= table->id[high].code)
|
|
return -EAGAIN; /* Incorrect reading */
|
|
return -EAGAIN; /* Incorrect reading */
|
|
|
|
|
|
while (low <= high) {
|
|
while (low <= high) {
|
|
- if (code >= table.id[mid].code &&
|
|
|
|
- code < table.id[mid - 1].code)
|
|
|
|
|
|
+ if (code >= table->id[mid].code &&
|
|
|
|
+ code < table->id[mid - 1].code)
|
|
break;
|
|
break;
|
|
- else if (code < table.id[mid].code)
|
|
|
|
|
|
+ else if (code < table->id[mid].code)
|
|
low = mid + 1;
|
|
low = mid + 1;
|
|
else
|
|
else
|
|
high = mid - 1;
|
|
high = mid - 1;
|
|
@@ -458,15 +480,15 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code,
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
case ADC_INCREMENT:
|
|
case ADC_INCREMENT:
|
|
- code &= table.data_mask;
|
|
|
|
- if (code < table.id[low].code)
|
|
|
|
|
|
+ code &= table->data_mask;
|
|
|
|
+ if (code < table->id[low].code)
|
|
return -EAGAIN; /* Incorrect reading */
|
|
return -EAGAIN; /* Incorrect reading */
|
|
|
|
|
|
while (low <= high) {
|
|
while (low <= high) {
|
|
- if (code <= table.id[mid].code &&
|
|
|
|
- code > table.id[mid - 1].code)
|
|
|
|
|
|
+ if (code <= table->id[mid].code &&
|
|
|
|
+ code > table->id[mid - 1].code)
|
|
break;
|
|
break;
|
|
- else if (code > table.id[mid].code)
|
|
|
|
|
|
+ else if (code > table->id[mid].code)
|
|
low = mid + 1;
|
|
low = mid + 1;
|
|
else
|
|
else
|
|
high = mid - 1;
|
|
high = mid - 1;
|
|
@@ -475,7 +497,8 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code,
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
- pr_err("Invalid the conversion table\n");
|
|
|
|
|
|
+ pr_err("%s: unknown table mode: %d\n", __func__, table->mode);
|
|
|
|
+ return -EINVAL;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -484,10 +507,10 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code,
|
|
* temperature between 2 table entries is linear and interpolate
|
|
* temperature between 2 table entries is linear and interpolate
|
|
* to produce less granular result.
|
|
* to produce less granular result.
|
|
*/
|
|
*/
|
|
- num = table.id[mid].temp - table.id[mid - 1].temp;
|
|
|
|
- num *= abs(table.id[mid - 1].code - code);
|
|
|
|
- denom = abs(table.id[mid - 1].code - table.id[mid].code);
|
|
|
|
- *temp = table.id[mid - 1].temp + (num / denom);
|
|
|
|
|
|
+ num = table->id[mid].temp - table->id[mid - 1].temp;
|
|
|
|
+ num *= abs(table->id[mid - 1].code - code);
|
|
|
|
+ denom = abs(table->id[mid - 1].code - table->id[mid].code);
|
|
|
|
+ *temp = table->id[mid - 1].temp + (num / denom);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -638,7 +661,7 @@ static void rk_tsadcv3_control(void __iomem *regs, bool enable)
|
|
writel_relaxed(val, regs + TSADCV2_AUTO_CON);
|
|
writel_relaxed(val, regs + TSADCV2_AUTO_CON);
|
|
}
|
|
}
|
|
|
|
|
|
-static int rk_tsadcv2_get_temp(struct chip_tsadc_table table,
|
|
|
|
|
|
+static int rk_tsadcv2_get_temp(const struct chip_tsadc_table *table,
|
|
int chn, void __iomem *regs, int *temp)
|
|
int chn, void __iomem *regs, int *temp)
|
|
{
|
|
{
|
|
u32 val;
|
|
u32 val;
|
|
@@ -648,39 +671,57 @@ static int rk_tsadcv2_get_temp(struct chip_tsadc_table table,
|
|
return rk_tsadcv2_code_to_temp(table, val, temp);
|
|
return rk_tsadcv2_code_to_temp(table, val, temp);
|
|
}
|
|
}
|
|
|
|
|
|
-static void rk_tsadcv2_alarm_temp(struct chip_tsadc_table table,
|
|
|
|
- int chn, void __iomem *regs, int temp)
|
|
|
|
|
|
+static int rk_tsadcv2_alarm_temp(const struct chip_tsadc_table *table,
|
|
|
|
+ int chn, void __iomem *regs, int temp)
|
|
{
|
|
{
|
|
- u32 alarm_value, int_en;
|
|
|
|
|
|
+ u32 alarm_value;
|
|
|
|
+ u32 int_en, int_clr;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * In some cases, some sensors didn't need the trip points, the
|
|
|
|
+ * set_trips will pass {-INT_MAX, INT_MAX} to trigger tsadc alarm
|
|
|
|
+ * in the end, ignore this case and disable the high temperature
|
|
|
|
+ * interrupt.
|
|
|
|
+ */
|
|
|
|
+ if (temp == INT_MAX) {
|
|
|
|
+ int_clr = readl_relaxed(regs + TSADCV2_INT_EN);
|
|
|
|
+ int_clr &= ~TSADCV2_INT_SRC_EN(chn);
|
|
|
|
+ writel_relaxed(int_clr, regs + TSADCV2_INT_EN);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
|
|
/* Make sure the value is valid */
|
|
/* Make sure the value is valid */
|
|
alarm_value = rk_tsadcv2_temp_to_code(table, temp);
|
|
alarm_value = rk_tsadcv2_temp_to_code(table, temp);
|
|
- if (alarm_value == table.data_mask)
|
|
|
|
- return;
|
|
|
|
|
|
+ if (alarm_value == table->data_mask)
|
|
|
|
+ return -ERANGE;
|
|
|
|
|
|
- writel_relaxed(alarm_value & table.data_mask,
|
|
|
|
|
|
+ writel_relaxed(alarm_value & table->data_mask,
|
|
regs + TSADCV2_COMP_INT(chn));
|
|
regs + TSADCV2_COMP_INT(chn));
|
|
|
|
|
|
int_en = readl_relaxed(regs + TSADCV2_INT_EN);
|
|
int_en = readl_relaxed(regs + TSADCV2_INT_EN);
|
|
int_en |= TSADCV2_INT_SRC_EN(chn);
|
|
int_en |= TSADCV2_INT_SRC_EN(chn);
|
|
writel_relaxed(int_en, regs + TSADCV2_INT_EN);
|
|
writel_relaxed(int_en, regs + TSADCV2_INT_EN);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-static void rk_tsadcv2_tshut_temp(struct chip_tsadc_table table,
|
|
|
|
- int chn, void __iomem *regs, int temp)
|
|
|
|
|
|
+static int rk_tsadcv2_tshut_temp(const struct chip_tsadc_table *table,
|
|
|
|
+ int chn, void __iomem *regs, int temp)
|
|
{
|
|
{
|
|
u32 tshut_value, val;
|
|
u32 tshut_value, val;
|
|
|
|
|
|
/* Make sure the value is valid */
|
|
/* Make sure the value is valid */
|
|
tshut_value = rk_tsadcv2_temp_to_code(table, temp);
|
|
tshut_value = rk_tsadcv2_temp_to_code(table, temp);
|
|
- if (tshut_value == table.data_mask)
|
|
|
|
- return;
|
|
|
|
|
|
+ if (tshut_value == table->data_mask)
|
|
|
|
+ return -ERANGE;
|
|
|
|
|
|
writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn));
|
|
writel_relaxed(tshut_value, regs + TSADCV2_COMP_SHUT(chn));
|
|
|
|
|
|
/* TSHUT will be valid */
|
|
/* TSHUT will be valid */
|
|
val = readl_relaxed(regs + TSADCV2_AUTO_CON);
|
|
val = readl_relaxed(regs + TSADCV2_AUTO_CON);
|
|
writel_relaxed(val | TSADCV2_AUTO_SRC_EN(chn), regs + TSADCV2_AUTO_CON);
|
|
writel_relaxed(val | TSADCV2_AUTO_SRC_EN(chn), regs + TSADCV2_AUTO_CON);
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
}
|
|
}
|
|
|
|
|
|
static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs,
|
|
static void rk_tsadcv2_tshut_mode(int chn, void __iomem *regs,
|
|
@@ -883,10 +924,8 @@ static int rockchip_thermal_set_trips(void *_sensor, int low, int high)
|
|
dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n",
|
|
dev_dbg(&thermal->pdev->dev, "%s: sensor %d: low: %d, high %d\n",
|
|
__func__, sensor->id, low, high);
|
|
__func__, sensor->id, low, high);
|
|
|
|
|
|
- tsadc->set_alarm_temp(tsadc->table,
|
|
|
|
- sensor->id, thermal->regs, high);
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
|
|
+ return tsadc->set_alarm_temp(&tsadc->table,
|
|
|
|
+ sensor->id, thermal->regs, high);
|
|
}
|
|
}
|
|
|
|
|
|
static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
|
|
static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
|
|
@@ -896,7 +935,7 @@ static int rockchip_thermal_get_temp(void *_sensor, int *out_temp)
|
|
const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip;
|
|
const struct rockchip_tsadc_chip *tsadc = sensor->thermal->chip;
|
|
int retval;
|
|
int retval;
|
|
|
|
|
|
- retval = tsadc->get_temp(tsadc->table,
|
|
|
|
|
|
+ retval = tsadc->get_temp(&tsadc->table,
|
|
sensor->id, thermal->regs, out_temp);
|
|
sensor->id, thermal->regs, out_temp);
|
|
dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n",
|
|
dev_dbg(&thermal->pdev->dev, "sensor %d - temp: %d, retval: %d\n",
|
|
sensor->id, *out_temp, retval);
|
|
sensor->id, *out_temp, retval);
|
|
@@ -982,8 +1021,12 @@ rockchip_thermal_register_sensor(struct platform_device *pdev,
|
|
int error;
|
|
int error;
|
|
|
|
|
|
tsadc->set_tshut_mode(id, thermal->regs, thermal->tshut_mode);
|
|
tsadc->set_tshut_mode(id, thermal->regs, thermal->tshut_mode);
|
|
- tsadc->set_tshut_temp(tsadc->table, id, thermal->regs,
|
|
|
|
|
|
+
|
|
|
|
+ error = tsadc->set_tshut_temp(&tsadc->table, id, thermal->regs,
|
|
thermal->tshut_temp);
|
|
thermal->tshut_temp);
|
|
|
|
+ if (error)
|
|
|
|
+ dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n",
|
|
|
|
+ __func__, thermal->tshut_temp, error);
|
|
|
|
|
|
sensor->thermal = thermal;
|
|
sensor->thermal = thermal;
|
|
sensor->id = id;
|
|
sensor->id = id;
|
|
@@ -1196,9 +1239,13 @@ static int __maybe_unused rockchip_thermal_resume(struct device *dev)
|
|
|
|
|
|
thermal->chip->set_tshut_mode(id, thermal->regs,
|
|
thermal->chip->set_tshut_mode(id, thermal->regs,
|
|
thermal->tshut_mode);
|
|
thermal->tshut_mode);
|
|
- thermal->chip->set_tshut_temp(thermal->chip->table,
|
|
|
|
|
|
+
|
|
|
|
+ error = thermal->chip->set_tshut_temp(&thermal->chip->table,
|
|
id, thermal->regs,
|
|
id, thermal->regs,
|
|
thermal->tshut_temp);
|
|
thermal->tshut_temp);
|
|
|
|
+ if (error)
|
|
|
|
+ dev_err(&pdev->dev, "%s: invalid tshut=%d, error=%d\n",
|
|
|
|
+ __func__, thermal->tshut_temp, error);
|
|
}
|
|
}
|
|
|
|
|
|
thermal->chip->control(thermal->regs, true);
|
|
thermal->chip->control(thermal->regs, true);
|