diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-26 09:23:43 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-05-26 09:23:43 -0700 |
commit | bfb764440d5bee109003295473a0b387bc799222 (patch) | |
tree | 23f4683f6aca3b75d81e009f1c8f9b201a6422c1 /drivers | |
parent | 159d08f4b85ce454cd05fb9e2c539276e148d366 (diff) | |
parent | 88ac99063e6e38bf9577e75f0d65dd02e2326d58 (diff) |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux
Pull thermal management updates from Zhang Rui:
- Introduce generic ADC thermal driver, based on OF thermal (Laxman
Dewangan)
- Introduce new thermal driver for Tango chips (Marc Gonzalez)
- Rockchip driver support for RK3399, RK3366, and some fixes (Caesar
Wang, Elaine Zhang and Shawn Lin)
- Add CPU power cooling model to Mediatek thermal driver (Dawei Chien)
- Wider usage of dev_thermal_zone_of_sensor_register (Eduardo Valentin)
- TI thermal driver gained a new maintainer (Keerthy).
- Enabled powerclamp driver by checking CPU feature and package cstate
counter instead of CPU whitelist (Jacob Pan)
- Various fixes on thermal governor, OF thermal, Tegra, and RCAR
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/rzhang/linux: (50 commits)
thermal: tango: initialize TEMPSI_CFG
thermal: rockchip: use the usleep_range instead of udelay
thermal: rockchip: add the notes for better reading
thermal: rockchip: Support RK3366 SoCs in the thermal driver
thermal: rockchip: handle the power sequence for tsadc controller
thermal: rockchip: update the tsadc table for rk3399
thermal: rockchip: fixes the code_to_temp for tsadc driver
thermal: rockchip: disable thermal->clk in err case
thermal: tegra: add Tegra132 specific SOC_THERM driver
thermal: fix ptr_ret.cocci warnings
thermal: mediatek: Add cpu dynamic power cooling model.
thermal: generic-adc: Add ADC based thermal sensor driver
thermal: generic-adc: Add DT binding for ADC based thermal sensor
thermal: tegra: fix static checker warning
thermal: tegra: mark PM functions __maybe_unused
thermal: add temperature sensor support for tango SoC
thermal: hisilicon: fix IRQ imbalance enabling
thermal: hisilicon: support to use any sensor
thermal: rcar: Remove binding docs for r8a7794
thermal: tegra: add PM support
...
Diffstat (limited to 'drivers')
30 files changed, 2271 insertions, 740 deletions
diff --git a/drivers/cpufreq/mt8173-cpufreq.c b/drivers/cpufreq/mt8173-cpufreq.c index 6f602c7a71bd..643f43179df1 100644 --- a/drivers/cpufreq/mt8173-cpufreq.c +++ b/drivers/cpufreq/mt8173-cpufreq.c @@ -307,17 +307,24 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, return 0; } +#define DYNAMIC_POWER "dynamic-power-coefficient" + static void mtk_cpufreq_ready(struct cpufreq_policy *policy) { struct mtk_cpu_dvfs_info *info = policy->driver_data; struct device_node *np = of_node_get(info->cpu_dev->of_node); + u32 capacitance = 0; if (WARN_ON(!np)) return; if (of_find_property(np, "#cooling-cells", NULL)) { - info->cdev = of_cpufreq_cooling_register(np, - policy->related_cpus); + of_property_read_u32(np, DYNAMIC_POWER, &capacitance); + + info->cdev = of_cpufreq_power_cooling_register(np, + policy->related_cpus, + capacitance, + NULL); if (IS_ERR(info->cdev)) { dev_err(info->cpu_dev, diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 0addc84ba948..69166ab3151d 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -77,7 +77,6 @@ static const u8 LM75_REG_TEMP[3] = { struct lm75_data { struct i2c_client *client; struct device *hwmon_dev; - struct thermal_zone_device *tz; struct mutex update_lock; u8 orig_conf; u8 resolution; /* In bits, between 9 and 12 */ @@ -306,11 +305,9 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) if (IS_ERR(data->hwmon_dev)) return PTR_ERR(data->hwmon_dev); - data->tz = thermal_zone_of_sensor_register(data->hwmon_dev, 0, - data->hwmon_dev, - &lm75_of_thermal_ops); - if (IS_ERR(data->tz)) - data->tz = NULL; + devm_thermal_zone_of_sensor_register(data->hwmon_dev, 0, + data->hwmon_dev, + &lm75_of_thermal_ops); dev_info(dev, "%s: sensor '%s'\n", dev_name(data->hwmon_dev), client->name); @@ -322,7 +319,6 @@ static int lm75_remove(struct i2c_client *client) { struct lm75_data *data = i2c_get_clientdata(client); - thermal_zone_of_sensor_unregister(data->hwmon_dev, data->tz); hwmon_device_unregister(data->hwmon_dev); lm75_write_value(client, LM75_REG_CONF, data->orig_conf); return 0; diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c index faa6e8dfbaaf..8ef7b713cb1a 100644 --- a/drivers/hwmon/ntc_thermistor.c +++ b/drivers/hwmon/ntc_thermistor.c @@ -259,7 +259,6 @@ struct ntc_data { struct device *dev; int n_comp; char name[PLATFORM_NAME_SIZE]; - struct thermal_zone_device *tz; }; #if defined(CONFIG_OF) && IS_ENABLED(CONFIG_IIO) @@ -579,6 +578,7 @@ static const struct thermal_zone_of_device_ops ntc_of_thermal_ops = { static int ntc_thermistor_probe(struct platform_device *pdev) { + struct thermal_zone_device *tz; const struct of_device_id *of_id = of_match_device(of_match_ptr(ntc_match), &pdev->dev); const struct platform_device_id *pdev_id; @@ -677,12 +677,10 @@ static int ntc_thermistor_probe(struct platform_device *pdev) dev_info(&pdev->dev, "Thermistor type: %s successfully probed.\n", pdev_id->name); - data->tz = thermal_zone_of_sensor_register(data->dev, 0, data->dev, - &ntc_of_thermal_ops); - if (IS_ERR(data->tz)) { + tz = devm_thermal_zone_of_sensor_register(data->dev, 0, data->dev, + &ntc_of_thermal_ops); + if (IS_ERR(tz)) dev_dbg(&pdev->dev, "Failed to register to thermal fw.\n"); - data->tz = NULL; - } return 0; err_after_sysfs: @@ -700,8 +698,6 @@ static int ntc_thermistor_remove(struct platform_device *pdev) sysfs_remove_group(&data->dev->kobj, &ntc_attr_group); ntc_iio_channel_release(pdata); - thermal_zone_of_sensor_unregister(data->dev, data->tz); - return 0; } diff --git a/drivers/hwmon/scpi-hwmon.c b/drivers/hwmon/scpi-hwmon.c index 912b449c8303..25b44e68926d 100644 --- a/drivers/hwmon/scpi-hwmon.c +++ b/drivers/hwmon/scpi-hwmon.c @@ -31,10 +31,8 @@ struct sensor_data { }; struct scpi_thermal_zone { - struct list_head list; int sensor_id; struct scpi_sensors *scpi_sensors; - struct thermal_zone_device *tzd; }; struct scpi_sensors { @@ -92,20 +90,6 @@ scpi_show_label(struct device *dev, struct device_attribute *attr, char *buf) return sprintf(buf, "%s\n", sensor->info.name); } -static void -unregister_thermal_zones(struct platform_device *pdev, - struct scpi_sensors *scpi_sensors) -{ - struct list_head *pos; - - list_for_each(pos, &scpi_sensors->thermal_zones) { - struct scpi_thermal_zone *zone; - - zone = list_entry(pos, struct scpi_thermal_zone, list); - thermal_zone_of_sensor_unregister(&pdev->dev, zone->tzd); - } -} - static struct thermal_zone_of_device_ops scpi_sensor_ops = { .get_temp = scpi_read_temp, }; @@ -118,7 +102,7 @@ static int scpi_hwmon_probe(struct platform_device *pdev) struct scpi_ops *scpi_ops; struct device *hwdev, *dev = &pdev->dev; struct scpi_sensors *scpi_sensors; - int ret, idx; + int idx, ret; scpi_ops = get_scpi_ops(); if (!scpi_ops) @@ -232,48 +216,35 @@ static int scpi_hwmon_probe(struct platform_device *pdev) INIT_LIST_HEAD(&scpi_sensors->thermal_zones); for (i = 0; i < nr_sensors; i++) { struct sensor_data *sensor = &scpi_sensors->data[i]; + struct thermal_zone_device *z; struct scpi_thermal_zone *zone; if (sensor->info.class != TEMPERATURE) continue; zone = devm_kzalloc(dev, sizeof(*zone), GFP_KERNEL); - if (!zone) { - ret = -ENOMEM; - goto unregister_tzd; - } + if (!zone) + return -ENOMEM; zone->sensor_id = i; zone->scpi_sensors = scpi_sensors; - zone->tzd = thermal_zone_of_sensor_register(dev, - sensor->info.sensor_id, zone, &scpi_sensor_ops); + z = devm_thermal_zone_of_sensor_register(dev, + sensor->info.sensor_id, + zone, + &scpi_sensor_ops); /* * The call to thermal_zone_of_sensor_register returns * an error for sensors that are not associated with * any thermal zones or if the thermal subsystem is * not configured. */ - if (IS_ERR(zone->tzd)) { + if (IS_ERR(z)) { devm_kfree(dev, zone); continue; } - list_add(&zone->list, &scpi_sensors->thermal_zones); } return 0; - -unregister_tzd: - unregister_thermal_zones(pdev, scpi_sensors); - return ret; -} - -static int scpi_hwmon_remove(struct platform_device *pdev) -{ - struct scpi_sensors *scpi_sensors = platform_get_drvdata(pdev); - - unregister_thermal_zones(pdev, scpi_sensors); - - return 0; } static const struct of_device_id scpi_of_match[] = { @@ -288,7 +259,6 @@ static struct platform_driver scpi_hwmon_platdrv = { .of_match_table = scpi_of_match, }, .probe = scpi_hwmon_probe, - .remove = scpi_hwmon_remove, }; module_platform_driver(scpi_hwmon_platdrv); diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c index 5289aa0980a8..f1e96fd7f445 100644 --- a/drivers/hwmon/tmp102.c +++ b/drivers/hwmon/tmp102.c @@ -53,7 +53,6 @@ struct tmp102 { struct i2c_client *client; struct device *hwmon_dev; - struct thermal_zone_device *tz; struct mutex lock; u16 config_orig; unsigned long last_update; @@ -232,10 +231,8 @@ static int tmp102_probe(struct i2c_client *client, goto fail_restore_config; } tmp102->hwmon_dev = hwmon_dev; - tmp102->tz = thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev, - &tmp102_of_thermal_ops); - if (IS_ERR(tmp102->tz)) - tmp102->tz = NULL; + devm_thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev, + &tmp102_of_thermal_ops); dev_info(dev, "initialized\n"); @@ -251,7 +248,6 @@ static int tmp102_remove(struct i2c_client *client) { struct tmp102 *tmp102 = i2c_get_clientdata(client); - thermal_zone_of_sensor_unregister(tmp102->hwmon_dev, tmp102->tz); hwmon_device_unregister(tmp102->hwmon_dev); /* Stop monitoring if device was stopped originally */ diff --git a/drivers/input/touchscreen/sun4i-ts.c b/drivers/input/touchscreen/sun4i-ts.c index 485794376ee5..d07dd29d4848 100644 --- a/drivers/input/touchscreen/sun4i-ts.c +++ b/drivers/input/touchscreen/sun4i-ts.c @@ -115,7 +115,6 @@ struct sun4i_ts_data { struct device *dev; struct input_dev *input; - struct thermal_zone_device *tz; void __iomem *base; unsigned int irq; bool ignore_fifo_data; @@ -366,10 +365,7 @@ static int sun4i_ts_probe(struct platform_device *pdev) if (IS_ERR(hwmon)) return PTR_ERR(hwmon); - ts->tz = thermal_zone_of_sensor_register(ts->dev, 0, ts, - &sun4i_ts_tz_ops); - if (IS_ERR(ts->tz)) - ts->tz = NULL; + devm_thermal_zone_of_sensor_register(ts->dev, 0, ts, &sun4i_ts_tz_ops); writel(TEMP_IRQ_EN(1), ts->base + TP_INT_FIFOC); @@ -377,7 +373,6 @@ static int sun4i_ts_probe(struct platform_device *pdev) error = input_register_device(ts->input); if (error) { writel(0, ts->base + TP_INT_FIFOC); - thermal_zone_of_sensor_unregister(ts->dev, ts->tz); return error; } } @@ -394,8 +389,6 @@ static int sun4i_ts_remove(struct platform_device *pdev) if (ts->input) input_unregister_device(ts->input); - thermal_zone_of_sensor_unregister(ts->dev, ts->tz); - /* Deactivate all IRQs */ writel(0, ts->base + TP_INT_FIFOC); diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index d89d60c8b6cf..2d702ca6556f 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -260,16 +260,6 @@ config ARMADA_THERMAL Enable this option if you want to have support for thermal management controller present in Armada 370 and Armada XP SoC. -config TEGRA_SOCTHERM - tristate "Tegra SOCTHERM thermal management" - depends on ARCH_TEGRA - help - Enable this option for integrated thermal management support on NVIDIA - Tegra124 systems-on-chip. The driver supports four thermal zones - (CPU, GPU, MEM, PLLX). Cooling devices can be bound to the thermal - zones to manage temperatures. This option is also required for the - emergency thermal reset (thermtrip) feature to function. - config DB8500_CPUFREQ_COOLING tristate "DB8500 cpufreq cooling" depends on ARCH_U8500 || COMPILE_TEST @@ -377,6 +367,17 @@ depends on ARCH_STI && OF source "drivers/thermal/st/Kconfig" endmenu +config TANGO_THERMAL + tristate "Tango thermal management" + depends on ARCH_TANGO || COMPILE_TEST + help + Enable the Tango thermal driver, which supports the primitive + temperature sensor embedded in Tango chips since the SMP8758. + This sensor only generates a 1-bit signal to indicate whether + the die temperature exceeds a programmable threshold. + +source "drivers/thermal/tegra/Kconfig" + config QCOM_SPMI_TEMP_ALARM tristate "Qualcomm SPMI PMIC Temperature Alarm" depends on OF && SPMI && IIO @@ -388,4 +389,14 @@ config QCOM_SPMI_TEMP_ALARM real time die temperature if an ADC is present or an estimate of the temperature based upon the over temperature stage value. +config GENERIC_ADC_THERMAL + tristate "Generic ADC based thermal sensor" + depends on IIO + help + This enabled a thermal sysfs driver for the temperature sensor + which is connected to the General Purpose ADC. The ADC channel + is read via IIO framework and the channel information is provided + to this driver. This driver reports the temperature by reading ADC + channel and converts it to temperature based on lookup table. + endif diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 8e9cbc3b5679..10b07c14f8a9 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -35,6 +35,7 @@ obj-y += samsung/ obj-$(CONFIG_DOVE_THERMAL) += dove_thermal.o obj-$(CONFIG_DB8500_THERMAL) += db8500_thermal.o obj-$(CONFIG_ARMADA_THERMAL) += armada_thermal.o +obj-$(CONFIG_TANGO_THERMAL) += tango_thermal.o obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o obj-$(CONFIG_DB8500_CPUFREQ_COOLING) += db8500_cpufreq_cooling.o obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o @@ -46,6 +47,7 @@ obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/ obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o obj-$(CONFIG_ST_THERMAL) += st/ -obj-$(CONFIG_TEGRA_SOCTHERM) += tegra_soctherm.o +obj-$(CONFIG_TEGRA_SOCTHERM) += tegra/ obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o obj-$(CONFIG_MTK_THERMAL) += mtk_thermal.o +obj-$(CONFIG_GENERIC_ADC_THERMAL) += thermal-generic-adc.o diff --git a/drivers/thermal/gov_bang_bang.c b/drivers/thermal/gov_bang_bang.c index 70836c5b89bc..fc52016d4e85 100644 --- a/drivers/thermal/gov_bang_bang.c +++ b/drivers/thermal/gov_bang_bang.c @@ -29,7 +29,13 @@ static void thermal_zone_trip_update(struct thermal_zone_device *tz, int trip) struct thermal_instance *instance; tz->ops->get_trip_temp(tz, trip, &trip_temp); - tz->ops->get_trip_hyst(tz, trip, &trip_hyst); + + if (!tz->ops->get_trip_hyst) { + pr_warn_once("Undefined get_trip_hyst for thermal zone %s - " + "running with default hysteresis zero\n", tz->type); + trip_hyst = 0; + } else + tz->ops->get_trip_hyst(tz, trip, &trip_hyst); dev_dbg(&tz->device, "Trip%d[temp=%d]:temp=%d:hyst=%d\n", trip, trip_temp, tz->temperature, diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 5e820b541506..97fad8f51e1c 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -160,7 +160,7 @@ static int hisi_thermal_get_temp(void *_sensor, int *temp) struct hisi_thermal_sensor *sensor = _sensor; struct hisi_thermal_data *data = sensor->thermal; - int sensor_id = 0, i; + int sensor_id = -1, i; long max_temp = 0; *temp = hisi_thermal_get_sensor_temp(data, sensor); @@ -168,12 +168,19 @@ static int hisi_thermal_get_temp(void *_sensor, int *temp) sensor->sensor_temp = *temp; for (i = 0; i < HISI_MAX_SENSORS; i++) { + if (!data->sensors[i].tzd) + continue; + if (data->sensors[i].sensor_temp >= max_temp) { max_temp = data->sensors[i].sensor_temp; sensor_id = i; } } + /* If no sensor has been enabled, then skip to enable irq */ + if (sensor_id == -1) + return 0; + mutex_lock(&data->thermal_lock); data->irq_bind_sensor = sensor_id; mutex_unlock(&data->thermal_lock); @@ -226,8 +233,12 @@ static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) sensor->thres_temp / 1000); mutex_unlock(&data->thermal_lock); - for (i = 0; i < HISI_MAX_SENSORS; i++) + for (i = 0; i < HISI_MAX_SENSORS; i++) { + if (!data->sensors[i].tzd) + continue; + thermal_zone_device_update(data->sensors[i].tzd); + } return IRQ_HANDLED; } @@ -243,10 +254,11 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, sensor->id = index; sensor->thermal = data; - sensor->tzd = thermal_zone_of_sensor_register(&pdev->dev, sensor->id, - sensor, &hisi_of_thermal_ops); + sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, + sensor->id, sensor, &hisi_of_thermal_ops); if (IS_ERR(sensor->tzd)) { ret = PTR_ERR(sensor->tzd); + sensor->tzd = NULL; dev_err(&pdev->dev, "failed to register sensor id %d: %d\n", sensor->id, ret); return ret; @@ -331,28 +343,21 @@ static int hisi_thermal_probe(struct platform_device *pdev) return ret; } + hisi_thermal_enable_bind_irq_sensor(data); + irq_get_irqchip_state(data->irq, IRQCHIP_STATE_MASKED, + &data->irq_enabled); + for (i = 0; i < HISI_MAX_SENSORS; ++i) { ret = hisi_thermal_register_sensor(pdev, data, &data->sensors[i], i); - if (ret) { + if (ret) dev_err(&pdev->dev, "failed to register thermal sensor: %d\n", ret); - goto err_get_sensor_data; - } + else + hisi_thermal_toggle_sensor(&data->sensors[i], true); } - hisi_thermal_enable_bind_irq_sensor(data); - data->irq_enabled = true; - - for (i = 0; i < HISI_MAX_SENSORS; i++) - hisi_thermal_toggle_sensor(&data->sensors[i], true); - return 0; - -err_get_sensor_data: - clk_disable_unprepare(data->clk); - - return ret; } static int hisi_thermal_remove(struct platform_device *pdev) @@ -363,8 +368,10 @@ static int hisi_thermal_remove(struct platform_device *pdev) for (i = 0; i < HISI_MAX_SENSORS; i++) { struct hisi_thermal_sensor *sensor = &data->sensors[i]; + if (!sensor->tzd) + continue; + hisi_thermal_toggle_sensor(sensor, false); - thermal_zone_of_sensor_unregister(&pdev->dev, sensor->tzd); } hisi_thermal_disable_sensor(data); diff --git a/drivers/thermal/int340x_thermal/processor_thermal_device.c b/drivers/thermal/int340x_thermal/processor_thermal_device.c index 36fa724a36c8..42c1ac057bad 100644 --- a/drivers/thermal/int340x_thermal/processor_thermal_device.c +++ b/drivers/thermal/int340x_thermal/processor_thermal_device.c @@ -198,49 +198,33 @@ static struct thermal_zone_device_ops proc_thermal_local_ops = { .get_temp = proc_thermal_get_zone_temp, }; -static int proc_thermal_add(struct device *dev, - struct proc_thermal_device **priv) +static int proc_thermal_read_ppcc(struct proc_thermal_device *proc_priv) { - struct proc_thermal_device *proc_priv; - struct acpi_device *adev; + int i; acpi_status status; struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *elements, *ppcc; union acpi_object *p; - unsigned long long tmp; - struct thermal_zone_device_ops *ops = NULL; - int i; - int ret; - - adev = ACPI_COMPANION(dev); - if (!adev) - return -ENODEV; + int ret = 0; - status = acpi_evaluate_object(adev->handle, "PPCC", NULL, &buf); + status = acpi_evaluate_object(proc_priv->adev->handle, "PPCC", + NULL, &buf); if (ACPI_FAILURE(status)) return -ENODEV; p = buf.pointer; if (!p || (p->type != ACPI_TYPE_PACKAGE)) { - dev_err(dev, "Invalid PPCC data\n"); + dev_err(proc_priv->dev, "Invalid PPCC data\n"); ret = -EFAULT; goto free_buffer; } + if (!p->package.count) { - dev_err(dev, "Invalid PPCC package size\n"); + dev_err(proc_priv->dev, "Invalid PPCC package size\n"); ret = -EFAULT; goto free_buffer; } - proc_priv = devm_kzalloc(dev, sizeof(*proc_priv), GFP_KERNEL); - if (!proc_priv) { - ret = -ENOMEM; - goto free_buffer; - } - - proc_priv->dev = dev; - proc_priv->adev = adev; - for (i = 0; i < min((int)p->package.count - 1, 2); ++i) { elements = &(p->package.elements[i+1]); if (elements->type != ACPI_TYPE_PACKAGE || @@ -257,12 +241,62 @@ static int proc_thermal_add(struct device *dev, proc_priv->power_limits[i].step_uw = ppcc[5].integer.value; } +free_buffer: + kfree(buf.pointer); + + return ret; +} + +#define PROC_POWER_CAPABILITY_CHANGED 0x83 +static void proc_thermal_notify(acpi_handle handle, u32 event, void *data) +{ + struct proc_thermal_device *proc_priv = data; + + if (!proc_priv) + return; + + switch (event) { + case PROC_POWER_CAPABILITY_CHANGED: + proc_thermal_read_ppcc(proc_priv); + int340x_thermal_zone_device_update(proc_priv->int340x_zone); + break; + default: + dev_err(proc_priv->dev, "Unsupported event [0x%x]\n", event); + break; + } +} + + +static int proc_thermal_add(struct device *dev, + struct proc_thermal_device **priv) +{ + struct proc_thermal_device *proc_priv; + struct acpi_device *adev; + acpi_status status; + unsigned long long tmp; + struct thermal_zone_device_ops *ops = NULL; + int ret; + + adev = ACPI_COMPANION(dev); + if (!adev) + return -ENODEV; + + proc_priv = devm_kzalloc(dev, sizeof(*proc_priv), GFP_KERNEL); + if (!proc_priv) + return -ENOMEM; + + proc_priv->dev = dev; + proc_priv->adev = adev; *priv = proc_priv; - ret = sysfs_create_group(&dev->kobj, - &power_limit_attribute_group); + ret = proc_thermal_read_ppcc(proc_priv); + if (!ret) { + ret = sysfs_create_group(&dev->kobj, + &power_limit_attribute_group); + + } if (ret) - goto free_buffer; + return ret; status = acpi_evaluate_integer(adev->handle, "_TMP", NULL, &tmp); if (ACPI_FAILURE(status)) { @@ -274,20 +308,32 @@ static int proc_thermal_add(struct device *dev, proc_priv->int340x_zone = int340x_thermal_zone_add(adev, ops); if (IS_ERR(proc_priv->int340x_zone)) { - sysfs_remove_group(&proc_priv->dev->kobj, - &power_limit_attribute_group); ret = PTR_ERR(proc_priv->int340x_zone); + goto remove_group; } else ret = 0; -free_buffer: - kfree(buf.pointer); + ret = acpi_install_notify_handler(adev->handle, ACPI_DEVICE_NOTIFY, + proc_thermal_notify, + (void *)proc_priv); + if (ret) + goto remove_zone; + + return 0; + +remove_zone: + int340x_thermal_zone_remove(proc_priv->int340x_zone); +remove_group: + sysfs_remove_group(&proc_priv->dev->kobj, + &power_limit_attribute_group); return ret; } static void proc_thermal_remove(struct proc_thermal_device *proc_priv) { + acpi_remove_notify_handler(proc_priv->adev->handle, + ACPI_DEVICE_NOTIFY, proc_thermal_notify); int340x_thermal_zone_remove(proc_priv->int340x_zone); sysfs_remove_group(&proc_priv->dev->kobj, &power_limit_attribute_group); diff --git a/drivers/thermal/intel_powerclamp.c b/drivers/thermal/intel_powerclamp.c index 6c79588251d5..015ce2eb6eb7 100644 --- a/drivers/thermal/intel_powerclamp.c +++ b/drivers/thermal/intel_powerclamp.c @@ -510,12 +510,6 @@ static int start_power_clamp(void) unsigned long cpu; struct task_struct *thread; - /* check if pkg cstate counter is completely 0, abort in this case */ - if (!has_pkg_state_counter()) { - pr_err("pkg cstate counter not functional, abort\n"); - return -EINVAL; - } - set_target_ratio = clamp(set_target_ratio, 0U, MAX_TARGET_RATIO - 1); /* prevent cpu hotplug */ get_online_cpus(); @@ -672,35 +666,11 @@ static struct thermal_cooling_device_ops powerclamp_cooling_ops = { .set_cur_state = powerclamp_set_cur_state, }; -/* runs on Nehalem and later */ static const struct x86_cpu_id intel_powerclamp_ids[] __initconst = { - { X86_VENDOR_INTEL, 6, 0x1a}, - { X86_VENDOR_INTEL, 6, 0x1c}, - { X86_VENDOR_INTEL, 6, 0x1e}, - { X86_VENDOR_INTEL, 6, 0x1f}, - { X86_VENDOR_INTEL, 6, 0x25}, - { X86_VENDOR_INTEL, 6, 0x26}, - { X86_VENDOR_INTEL, 6, 0x2a}, - { X86_VENDOR_INTEL, 6, 0x2c}, - { X86_VENDOR_INTEL, 6, 0x2d}, - { X86_VENDOR_INTEL, 6, 0x2e}, - { X86_VENDOR_INTEL, 6, 0x2f}, - { X86_VENDOR_INTEL, 6, 0x37}, - { X86_VENDOR_INTEL, 6, 0x3a}, - { X86_VENDOR_INTEL, 6, 0x3c}, - { X86_VENDOR_INTEL, 6, 0x3d}, - { X86_VENDOR_INTEL, 6, 0x3e}, - { X86_VENDOR_INTEL, 6, 0x3f}, - { X86_VENDOR_INTEL, 6, 0x45}, - { X86_VENDOR_INTEL, 6, 0x46}, - { X86_VENDOR_INTEL, 6, 0x47}, - { X86_VENDOR_INTEL, 6, 0x4c}, - { X86_VENDOR_INTEL, 6, 0x4d}, - { X86_VENDOR_INTEL, 6, 0x4e}, - { X86_VENDOR_INTEL, 6, 0x4f}, - { X86_VENDOR_INTEL, 6, 0x56}, - { X86_VENDOR_INTEL, 6, 0x57}, - { X86_VENDOR_INTEL, 6, 0x5e}, + { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_MWAIT }, + { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_ARAT }, + { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_NONSTOP_TSC }, + { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_CONSTANT_TSC}, {} }; MODULE_DEVICE_TABLE(x86cpu, intel_powerclamp_ids); @@ -712,11 +682,12 @@ static int __init powerclamp_probe(void) boot_cpu_data.x86, boot_cpu_data.x86_model); return -ENODEV; } - if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC) || - !boot_cpu_has(X86_FEATURE_CONSTANT_TSC) || - !boot_cpu_has(X86_FEATURE_MWAIT) || - !boot_cpu_has(X86_FEATURE_ARAT)) + + /* The goal for idle time alignment is to achieve package cstate. */ + if (!has_pkg_state_counter()) { + pr_info("No package C-state available"); return -ENODEV; + } /* find the deepest mwait value */ find_target_mwait(); diff --git a/drivers/thermal/mtk_thermal.c b/drivers/thermal/mtk_thermal.c index 507632b9648e..262ab0a2266f 100644 --- a/drivers/thermal/mtk_thermal.c +++ b/drivers/thermal/mtk_thermal.c @@ -144,7 +144,6 @@ struct mtk_thermal { s32 o_slope; s32 vts[MT8173_NUM_SENSORS]; - struct thermal_zone_device *tzd; }; struct mtk_thermal_bank_cfg { @@ -572,16 +571,11 @@ static int mtk_thermal_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mt); - mt->tzd = thermal_zone_of_sensor_register(&pdev->dev, 0, mt, - &mtk_thermal_ops); - if (IS_ERR(mt->tzd)) - goto err_register; + devm_thermal_zone_of_sensor_register(&pdev->dev, 0, mt, + &mtk_thermal_ops); return 0; -err_register: - clk_disable_unprepare(mt->clk_peri_therm); - err_disable_clk_auxadc: clk_disable_unprepare(mt->clk_auxadc); @@ -592,8 +586,6 @@ static int mtk_thermal_remove(struct platform_device *pdev) { struct mtk_thermal *mt = platform_get_drvdata(pdev); - thermal_zone_of_sensor_unregister(&pdev->dev, mt->tzd); - clk_disable_unprepare(mt->clk_peri_therm); clk_disable_unprepare(mt->clk_auxadc); diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c index d8ec44b194d6..b8e509c60848 100644 --- a/drivers/thermal/of-thermal.c +++ b/ |