Commit bb6c01c2 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux

Pull thermal management fixes from Zhang Rui:

 - fix a regression that thermal zone dynamically allocated sysfs
   attributes are freed before they're removed, which is introduced in
   4.10-rc1 (Jacob von Chorus)

 - fix a boot warning because deprecated hwmon API is used (Fabio
   Estevam)

 - a couple of fixes for rockchip thermal driver (Brian Norris, Caesar
   Wang)

* 'for-rc' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux:
  thermal: rockchip: fixes the conversion table
  thermal: core: move tz->device.groups cleanup to thermal_release
  thermal: thermal_hwmon: Convert to hwmon_device_register_with_info()
  thermal: rockchip: handle set_trips without the trip points
  thermal: rockchip: optimize the conversion table
  thermal: rockchip: fixes invalid temperature case
  thermal: rockchip: don't pass table structs by value
  thermal: rockchip: improve conversion error messages
parents c497f8d1 bad94f80
...@@ -118,12 +118,12 @@ struct rockchip_tsadc_chip { ...@@ -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 (*set_alarm_temp)(const struct chip_tsadc_table *table,
int chn, void __iomem *reg, int temp); int chn, void __iomem *reg, int temp);
void (*set_tshut_temp)(struct chip_tsadc_table table, int (*set_tshut_temp)(const struct chip_tsadc_table *table,
int chn, void __iomem *reg, int temp); 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[] = { ...@@ -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[] = { ...@@ -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) { if (temp < table->id[low].temp || temp > table->id[high].temp)
error = table.data_mask;
goto exit; goto exit;
}
while (low <= high) { while (low <= high) {
if (temp == table.id[mid].temp) if (temp == table->id[mid].temp)
return table.id[mid].code; return table->id[mid].code;
else if (temp < table.id[mid].temp) 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, static int rk_tsadcv2_code_to_temp(const struct chip_tsadc_table *table,
int *temp) 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; code &= table->data_mask;
if (code < table.id[high].code) 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 && if (code >= table->id[mid].code &&
code < table.id[mid - 1].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, ...@@ -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; code &= table->data_mask;
if (code < table.id[low].code) 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 && if (code <= table->id[mid].code &&
code > table.id[mid - 1].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, ...@@ -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, ...@@ -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 = table->id[mid].temp - table->id[mid - 1].temp;
num *= abs(table.id[mid - 1].code - code); num *= abs(table->id[mid - 1].code - code);
denom = abs(table.id[mid - 1].code - table.id[mid].code); denom = abs(table->id[mid - 1].code - table->id[mid].code);
*temp = table.id[mid - 1].temp + (num / denom); *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) ...@@ -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, ...@@ -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, static int rk_tsadcv2_alarm_temp(const struct chip_tsadc_table *table,
int chn, void __iomem *regs, int temp) 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) if (alarm_value == table->data_mask)
return; 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, static int rk_tsadcv2_tshut_temp(const struct chip_tsadc_table *table,
int chn, void __iomem *regs, int temp) 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) if (tshut_value == table->data_mask)
return; 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) ...@@ -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, return tsadc->set_alarm_temp(&tsadc->table,
sensor->id, thermal->regs, high); sensor->id, thermal->regs, high);
return 0;
} }
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) ...@@ -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, ...@@ -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) ...@@ -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);
......
...@@ -799,6 +799,11 @@ static void thermal_release(struct device *dev) ...@@ -799,6 +799,11 @@ static void thermal_release(struct device *dev)
if (!strncmp(dev_name(dev), "thermal_zone", if (!strncmp(dev_name(dev), "thermal_zone",
sizeof("thermal_zone") - 1)) { sizeof("thermal_zone") - 1)) {
tz = to_thermal_zone(dev); tz = to_thermal_zone(dev);
kfree(tz->trip_type_attrs);
kfree(tz->trip_temp_attrs);
kfree(tz->trip_hyst_attrs);
kfree(tz->trips_attribute_group.attrs);
kfree(tz->device.groups);
kfree(tz); kfree(tz);
} else if (!strncmp(dev_name(dev), "cooling_device", } else if (!strncmp(dev_name(dev), "cooling_device",
sizeof("cooling_device") - 1)) { sizeof("cooling_device") - 1)) {
...@@ -1305,10 +1310,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) ...@@ -1305,10 +1310,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
thermal_zone_device_set_polling(tz, 0); thermal_zone_device_set_polling(tz, 0);
kfree(tz->trip_type_attrs);
kfree(tz->trip_temp_attrs);
kfree(tz->trip_hyst_attrs);
kfree(tz->trips_attribute_group.attrs);
thermal_set_governor(tz, NULL); thermal_set_governor(tz, NULL);
thermal_remove_hwmon_sysfs(tz); thermal_remove_hwmon_sysfs(tz);
...@@ -1316,7 +1317,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz) ...@@ -1316,7 +1317,6 @@ void thermal_zone_device_unregister(struct thermal_zone_device *tz)
idr_destroy(&tz->idr); idr_destroy(&tz->idr);
mutex_destroy(&tz->lock); mutex_destroy(&tz->lock);
device_unregister(&tz->device); device_unregister(&tz->device);
kfree(tz->device.groups);
} }
EXPORT_SYMBOL_GPL(thermal_zone_device_unregister); EXPORT_SYMBOL_GPL(thermal_zone_device_unregister);
......
...@@ -58,14 +58,6 @@ static LIST_HEAD(thermal_hwmon_list); ...@@ -58,14 +58,6 @@ static LIST_HEAD(thermal_hwmon_list);
static DEFINE_MUTEX(thermal_hwmon_list_lock); static DEFINE_MUTEX(thermal_hwmon_list_lock);
static ssize_t
name_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct thermal_hwmon_device *hwmon = dev_get_drvdata(dev);
return sprintf(buf, "%s\n", hwmon->type);
}
static DEVICE_ATTR_RO(name);
static ssize_t static ssize_t
temp_input_show(struct device *dev, struct device_attribute *attr, char *buf) temp_input_show(struct device *dev, struct device_attribute *attr, char *buf)
{ {
...@@ -165,15 +157,12 @@ int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) ...@@ -165,15 +157,12 @@ int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
INIT_LIST_HEAD(&hwmon->tz_list); INIT_LIST_HEAD(&hwmon->tz_list);
strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH); strlcpy(hwmon->type, tz->type, THERMAL_NAME_LENGTH);
hwmon->device = hwmon_device_register(NULL); hwmon->device = hwmon_device_register_with_info(NULL, hwmon->type,
hwmon, NULL, NULL);
if (IS_ERR(hwmon->device)) { if (IS_ERR(hwmon->device)) {
result = PTR_ERR(hwmon->device); result = PTR_ERR(hwmon->device);
goto free_mem; goto free_mem;
} }
dev_set_drvdata(hwmon->device, hwmon);
result = device_create_file(hwmon->device, &dev_attr_name);
if (result)
goto free_mem;
register_sys_interface: register_sys_interface:
temp = kzalloc(sizeof(*temp), GFP_KERNEL); temp = kzalloc(sizeof(*temp), GFP_KERNEL);
...@@ -222,10 +211,8 @@ int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) ...@@ -222,10 +211,8 @@ int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz)
free_temp_mem: free_temp_mem:
kfree(temp); kfree(temp);
unregister_name: unregister_name:
if (new_hwmon_device) { if (new_hwmon_device)
device_remove_file(hwmon->device, &dev_attr_name);
hwmon_device_unregister(hwmon->device); hwmon_device_unregister(hwmon->device);
}
free_mem: free_mem:
if (new_hwmon_device) if (new_hwmon_device)
kfree(hwmon); kfree(hwmon);
...@@ -267,7 +254,6 @@ void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) ...@@ -267,7 +254,6 @@ void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz)
list_del(&hwmon->node); list_del(&hwmon->node);
mutex_unlock(&thermal_hwmon_list_lock); mutex_unlock(&thermal_hwmon_list_lock);
device_remove_file(hwmon->device, &dev_attr_name);
hwmon_device_unregister(hwmon->device); hwmon_device_unregister(hwmon->device);
kfree(hwmon); kfree(hwmon);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment