diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-26 12:04:29 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-26 12:04:29 -0700 |
| commit | 0ef7791e2bfb2e10aa95dc492eab72074cef9942 (patch) | |
| tree | 8b14a15cddceaf05c116b57ad59212fe651fb26a /drivers | |
| parent | befa93633193e5327e4045d1e5fa29114580fa5d (diff) | |
| parent | 760eea43f8c6d48684f1f34b8a02fddc1456e849 (diff) | |
| download | linux-0ef7791e2bfb2e10aa95dc492eab72074cef9942.tar.gz linux-0ef7791e2bfb2e10aa95dc492eab72074cef9942.tar.bz2 linux-0ef7791e2bfb2e10aa95dc492eab72074cef9942.zip | |
Merge branch 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal
Pull thermal SoC updates from Eduardo Valentin:
"Several new things coming up. Specifics:
- Rework of tsens and hisi thermal drivers
- OF-thermal now allows sharing multiple cooling devices on maps
- Added support for r8a7744 and R8A77970 on rcar thermal driver
- Added support for r8a774a1 on rcar_gen3 thermal driver
- New thermal driver stm32
- Fixes on multiple thermal drivers: of-thermal, imx, qoriq, armada,
qcom-spmi, rcar, da9062/61"
* 'linus' of git://git.kernel.org/pub/scm/linux/kernel/git/evalenti/linux-soc-thermal: (41 commits)
thermal: da9062/61: Prevent hardware access during system suspend
thermal: rcar_thermal: Prevent doing work after unbind
thermal: rcar_thermal: Prevent hardware access during system suspend
thermal: rcar_gen3_thermal: add R8A77980 support
dt-bindings: thermal: rcar-gen3-thermal: document R8A77980 bindings
thermal: add stm32 thermal driver
dt-bindings: stm32-thermal: add binding documentation
thermal: rcar_thermal: add R8A77970 support
dt-bindings: thermal: rcar-thermal: document R8A77970 bindings
thermal: rcar_thermal: fix duplicate IRQ request
dt-bindings: thermal: rcar: Add device tree support for r8a7744
thermal/drivers/hisi: Add the dual clusters sensors for hi3660
thermal/drivers/hisi: Add more sensors channel
thermal/drivers/hisi: Remove pointless irq field
thermal/drivers/hisi: Use platform_get_irq_byname
thermal/drivers/hisi: Replace macro name with relevant sensor location
thermal/drivers/hisi: Add multiple sensors support
thermal/drivers/hisi: Prepare to support multiple sensors
thermal/drivers/hisi: Factor out the probe functions
thermal/drivers/hisi: Set the thermal zone private data to the sensor pointer
...
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/thermal/Kconfig | 2 | ||||
| -rw-r--r-- | drivers/thermal/Makefile | 2 | ||||
| -rw-r--r-- | drivers/thermal/armada_thermal.c | 4 | ||||
| -rw-r--r-- | drivers/thermal/da9062-thermal.c | 4 | ||||
| -rw-r--r-- | drivers/thermal/hisi_thermal.c | 249 | ||||
| -rw-r--r-- | drivers/thermal/imx_thermal.c | 31 | ||||
| -rw-r--r-- | drivers/thermal/of-thermal.c | 152 | ||||
| -rw-r--r-- | drivers/thermal/qcom-spmi-temp-alarm.c | 158 | ||||
| -rw-r--r-- | drivers/thermal/qcom/tsens-8916.c | 12 | ||||
| -rw-r--r-- | drivers/thermal/qcom/tsens-8960.c | 41 | ||||
| -rw-r--r-- | drivers/thermal/qcom/tsens-8974.c | 12 | ||||
| -rw-r--r-- | drivers/thermal/qcom/tsens-common.c | 62 | ||||
| -rw-r--r-- | drivers/thermal/qcom/tsens-v2.c | 8 | ||||
| -rw-r--r-- | drivers/thermal/qcom/tsens.c | 19 | ||||
| -rw-r--r-- | drivers/thermal/qcom/tsens.h | 23 | ||||
| -rw-r--r-- | drivers/thermal/qoriq_thermal.c | 5 | ||||
| -rw-r--r-- | drivers/thermal/rcar_gen3_thermal.c | 2 | ||||
| -rw-r--r-- | drivers/thermal/rcar_thermal.c | 11 | ||||
| -rw-r--r-- | drivers/thermal/st/Kconfig | 14 | ||||
| -rw-r--r-- | drivers/thermal/st/Makefile | 1 | ||||
| -rw-r--r-- | drivers/thermal/st/stm_thermal.c | 760 |
21 files changed, 1287 insertions, 285 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 0e69edc77d18..5422523c03f8 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -432,7 +432,7 @@ source "drivers/thermal/samsung/Kconfig" endmenu menu "STMicroelectronics thermal drivers" -depends on ARCH_STI && OF +depends on (ARCH_STI || ARCH_STM32) && OF source "drivers/thermal/st/Kconfig" endmenu diff --git a/drivers/thermal/Makefile b/drivers/thermal/Makefile index 610344eb3e03..82bb50dc6423 100644 --- a/drivers/thermal/Makefile +++ b/drivers/thermal/Makefile @@ -53,7 +53,7 @@ obj-$(CONFIG_TI_SOC_THERMAL) += ti-soc-thermal/ obj-$(CONFIG_INT340X_THERMAL) += int340x_thermal/ obj-$(CONFIG_INTEL_BXT_PMIC_THERMAL) += intel_bxt_pmic_thermal.o obj-$(CONFIG_INTEL_PCH_THERMAL) += intel_pch_thermal.o -obj-$(CONFIG_ST_THERMAL) += st/ +obj-y += st/ obj-$(CONFIG_QCOM_TSENS) += qcom/ obj-y += tegra/ obj-$(CONFIG_HISI_THERMAL) += hisi_thermal.o diff --git a/drivers/thermal/armada_thermal.c b/drivers/thermal/armada_thermal.c index 2c2f6d93034e..92f67d40f2e9 100644 --- a/drivers/thermal/armada_thermal.c +++ b/drivers/thermal/armada_thermal.c @@ -526,8 +526,8 @@ static int armada_thermal_probe_legacy(struct platform_device *pdev, /* First memory region points towards the status register */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (IS_ERR(res)) - return PTR_ERR(res); + if (!res) + return -EIO; /* * Edit the resource start address and length to map over all the diff --git a/drivers/thermal/da9062-thermal.c b/drivers/thermal/da9062-thermal.c index dd8dd947b7f0..01b0cb994457 100644 --- a/drivers/thermal/da9062-thermal.c +++ b/drivers/thermal/da9062-thermal.c @@ -106,7 +106,7 @@ static void da9062_thermal_poll_on(struct work_struct *work) THERMAL_EVENT_UNSPECIFIED); delay = msecs_to_jiffies(thermal->zone->passive_delay); - schedule_delayed_work(&thermal->work, delay); + queue_delayed_work(system_freezable_wq, &thermal->work, delay); return; } @@ -125,7 +125,7 @@ static irqreturn_t da9062_thermal_irq_handler(int irq, void *data) struct da9062_thermal *thermal = data; disable_irq_nosync(thermal->irq); - schedule_delayed_work(&thermal->work, 0); + queue_delayed_work(system_freezable_wq, &thermal->work, 0); return IRQ_HANDLED; } diff --git a/drivers/thermal/hisi_thermal.c b/drivers/thermal/hisi_thermal.c index 761d0559c268..c4111a98f1a7 100644 --- a/drivers/thermal/hisi_thermal.c +++ b/drivers/thermal/hisi_thermal.c @@ -55,25 +55,39 @@ #define HI3660_TEMP_STEP (205) #define HI3660_TEMP_LAG (4000) -#define HI6220_DEFAULT_SENSOR 2 -#define HI3660_DEFAULT_SENSOR 1 +#define HI6220_CLUSTER0_SENSOR 2 +#define HI6220_CLUSTER1_SENSOR 1 + +#define HI3660_LITTLE_SENSOR 0 +#define HI3660_BIG_SENSOR 1 +#define HI3660_G3D_SENSOR 2 +#define HI3660_MODEM_SENSOR 3 + +struct hisi_thermal_data; struct hisi_thermal_sensor { + struct hisi_thermal_data *data; struct thermal_zone_device *tzd; + const char *irq_name; uint32_t id; uint32_t thres_temp; }; +struct hisi_thermal_ops { + int (*get_temp)(struct hisi_thermal_sensor *sensor); + int (*enable_sensor)(struct hisi_thermal_sensor *sensor); + int (*disable_sensor)(struct hisi_thermal_sensor *sensor); + int (*irq_handler)(struct hisi_thermal_sensor *sensor); + int (*probe)(struct hisi_thermal_data *data); +}; + struct hisi_thermal_data { - int (*get_temp)(struct hisi_thermal_data *data); - int (*enable_sensor)(struct hisi_thermal_data *data); - int (*disable_sensor)(struct hisi_thermal_data *data); - int (*irq_handler)(struct hisi_thermal_data *data); + const struct hisi_thermal_ops *ops; + struct hisi_thermal_sensor *sensor; struct platform_device *pdev; struct clk *clk; - struct hisi_thermal_sensor sensor; void __iomem *regs; - int irq; + int nr_sensors; }; /* @@ -266,30 +280,40 @@ static inline void hi6220_thermal_hdak_set(void __iomem *addr, int value) (value << 4), addr + HI6220_TEMP0_CFG); } -static int hi6220_thermal_irq_handler(struct hisi_thermal_data *data) +static int hi6220_thermal_irq_handler(struct hisi_thermal_sensor *sensor) { + struct hisi_thermal_data *data = sensor->data; + hi6220_thermal_alarm_clear(data->regs, 1); return 0; } -static int hi3660_thermal_irq_handler(struct hisi_thermal_data *data) +static int hi3660_thermal_irq_handler(struct hisi_thermal_sensor *sensor) { - hi3660_thermal_alarm_clear(data->regs, data->sensor.id, 1); + struct hisi_thermal_data *data = sensor->data; + + hi3660_thermal_alarm_clear(data->regs, sensor->id, 1); return 0; } -static int hi6220_thermal_get_temp(struct hisi_thermal_data *data) +static int hi6220_thermal_get_temp(struct hisi_thermal_sensor *sensor) { + struct hisi_thermal_data *data = sensor->data; + return hi6220_thermal_get_temperature(data->regs); } -static int hi3660_thermal_get_temp(struct hisi_thermal_data *data) +static int hi3660_thermal_get_temp(struct hisi_thermal_sensor *sensor) { - return hi3660_thermal_get_temperature(data->regs, data->sensor.id); + struct hisi_thermal_data *data = sensor->data; + + return hi3660_thermal_get_temperature(data->regs, sensor->id); } -static int hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) +static int hi6220_thermal_disable_sensor(struct hisi_thermal_sensor *sensor) { + struct hisi_thermal_data *data = sensor->data; + /* disable sensor module */ hi6220_thermal_enable(data->regs, 0); hi6220_thermal_alarm_enable(data->regs, 0); @@ -300,16 +324,18 @@ static int hi6220_thermal_disable_sensor(struct hisi_thermal_data *data) return 0; } -static int hi3660_thermal_disable_sensor(struct hisi_thermal_data *data) +static int hi3660_thermal_disable_sensor(struct hisi_thermal_sensor *sensor) { + struct hisi_thermal_data *data = sensor->data; + /* disable sensor module */ - hi3660_thermal_alarm_enable(data->regs, data->sensor.id, 0); + hi3660_thermal_alarm_enable(data->regs, sensor->id, 0); return 0; } -static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) +static int hi6220_thermal_enable_sensor(struct hisi_thermal_sensor *sensor) { - struct hisi_thermal_sensor *sensor = &data->sensor; + struct hisi_thermal_data *data = sensor->data; int ret; /* enable clock for tsensor */ @@ -345,10 +371,10 @@ static int hi6220_thermal_enable_sensor(struct hisi_thermal_data *data) return 0; } -static int hi3660_thermal_enable_sensor(struct hisi_thermal_data *data) +static int hi3660_thermal_enable_sensor(struct hisi_thermal_sensor *sensor) { unsigned int value; - struct hisi_thermal_sensor *sensor = &data->sensor; + struct hisi_thermal_data *data = sensor->data; /* disable interrupt */ hi3660_thermal_alarm_enable(data->regs, sensor->id, 0); @@ -371,21 +397,8 @@ static int hi6220_thermal_probe(struct hisi_thermal_data *data) { struct platform_device *pdev = data->pdev; struct device *dev = &pdev->dev; - struct resource *res; int ret; - data->get_temp = hi6220_thermal_get_temp; - data->enable_sensor = hi6220_thermal_enable_sensor; - data->disable_sensor = hi6220_thermal_disable_sensor; - data->irq_handler = hi6220_thermal_irq_handler; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data->regs = devm_ioremap_resource(dev, res); - if (IS_ERR(data->regs)) { - dev_err(dev, "failed to get io address\n"); - return PTR_ERR(data->regs); - } - data->clk = devm_clk_get(dev, "thermal_clk"); if (IS_ERR(data->clk)) { ret = PTR_ERR(data->clk); @@ -394,11 +407,14 @@ static int hi6220_thermal_probe(struct hisi_thermal_data *data) return ret; } - data->irq = platform_get_irq(pdev, 0); - if (data->irq < 0) - return data->irq; + data->sensor = devm_kzalloc(dev, sizeof(*data->sensor), GFP_KERNEL); + if (!data->sensor) + return -ENOMEM; - data->sensor.id = HI6220_DEFAULT_SENSOR; + data->sensor[0].id = HI6220_CLUSTER0_SENSOR; + data->sensor[0].irq_name = "tsensor_intr"; + data->sensor[0].data = data; + data->nr_sensors = 1; return 0; } @@ -407,38 +423,34 @@ static int hi3660_thermal_probe(struct hisi_thermal_data *data) { struct platform_device *pdev = data->pdev; struct device *dev = &pdev->dev; - struct resource *res; - data->get_temp = hi3660_thermal_get_temp; - data->enable_sensor = hi3660_thermal_enable_sensor; - data->disable_sensor = hi3660_thermal_disable_sensor; - data->irq_handler = hi3660_thermal_irq_handler; + data->nr_sensors = 2; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - data->regs = devm_ioremap_resource(dev, res); - if (IS_ERR(data->regs)) { - dev_err(dev, "failed to get io address\n"); - return PTR_ERR(data->regs); - } + data->sensor = devm_kzalloc(dev, sizeof(*data->sensor) * + data->nr_sensors, GFP_KERNEL); + if (!data->sensor) + return -ENOMEM; - data->irq = platform_get_irq(pdev, 0); - if (data->irq < 0) - return data->irq; + data->sensor[0].id = HI3660_BIG_SENSOR; + data->sensor[0].irq_name = "tsensor_a73"; + data->sensor[0].data = data; - data->sensor.id = HI3660_DEFAULT_SENSOR; + data->sensor[1].id = HI3660_LITTLE_SENSOR; + data->sensor[1].irq_name = "tsensor_a53"; + data->sensor[1].data = data; return 0; } static int hisi_thermal_get_temp(void *__data, int *temp) { - struct hisi_thermal_data *data = __data; - struct hisi_thermal_sensor *sensor = &data->sensor; + struct hisi_thermal_sensor *sensor = __data; + struct hisi_thermal_data *data = sensor->data; - *temp = data->get_temp(data); + *temp = data->ops->get_temp(sensor); - dev_dbg(&data->pdev->dev, "id=%d, temp=%d, thres=%d\n", - sensor->id, *temp, sensor->thres_temp); + dev_dbg(&data->pdev->dev, "tzd=%p, id=%d, temp=%d, thres=%d\n", + sensor->tzd, sensor->id, *temp, sensor->thres_temp); return 0; } @@ -449,38 +461,39 @@ static const struct thermal_zone_of_device_ops hisi_of_thermal_ops = { static irqreturn_t hisi_thermal_alarm_irq_thread(int irq, void *dev) { - struct hisi_thermal_data *data = dev; - struct hisi_thermal_sensor *sensor = &data->sensor; + struct hisi_thermal_sensor *sensor = dev; + struct hisi_thermal_data *data = sensor->data; int temp = 0; - data->irq_handler(data); + data->ops->irq_handler(sensor); - hisi_thermal_get_temp(data, &temp); + hisi_thermal_get_temp(sensor, &temp); if (temp >= sensor->thres_temp) { - dev_crit(&data->pdev->dev, "THERMAL ALARM: %d > %d\n", - temp, sensor->thres_temp); + dev_crit(&data->pdev->dev, + "sensor <%d> THERMAL ALARM: %d > %d\n", + sensor->id, temp, sensor->thres_temp); - thermal_zone_device_update(data->sensor.tzd, + thermal_zone_device_update(sensor->tzd, THERMAL_EVENT_UNSPECIFIED); } else { - dev_crit(&data->pdev->dev, "THERMAL ALARM stopped: %d < %d\n", - temp, sensor->thres_temp); + dev_crit(&data->pdev->dev, + "sensor <%d> THERMAL ALARM stopped: %d < %d\n", + sensor->id, temp, sensor->thres_temp); } return IRQ_HANDLED; } static int hisi_thermal_register_sensor(struct platform_device *pdev, - struct hisi_thermal_data *data, struct hisi_thermal_sensor *sensor) { int ret, i; const struct thermal_trip *trip; sensor->tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, - sensor->id, data, + sensor->id, sensor, &hisi_of_thermal_ops); if (IS_ERR(sensor->tzd)) { ret = PTR_ERR(sensor->tzd); @@ -502,14 +515,30 @@ static int hisi_thermal_register_sensor(struct platform_device *pdev, return 0; } +static const struct hisi_thermal_ops hi6220_ops = { + .get_temp = hi6220_thermal_get_temp, + .enable_sensor = hi6220_thermal_enable_sensor, + .disable_sensor = hi6220_thermal_disable_sensor, + .irq_handler = hi6220_thermal_irq_handler, + .probe = hi6220_thermal_probe, +}; + +static const struct hisi_thermal_ops hi3660_ops = { + .get_temp = hi3660_thermal_get_temp, + .enable_sensor = hi3660_thermal_enable_sensor, + .disable_sensor = hi3660_thermal_disable_sensor, + .irq_handler = hi3660_thermal_irq_handler, + .probe = hi3660_thermal_probe, +}; + static const struct of_device_id of_hisi_thermal_match[] = { { .compatible = "hisilicon,tsensor", - .data = hi6220_thermal_probe + .data = &hi6220_ops, }, { .compatible = "hisilicon,hi3660-tsensor", - .data = hi3660_thermal_probe + .data = &hi3660_ops, }, { /* end */ } }; @@ -527,9 +556,9 @@ static void hisi_thermal_toggle_sensor(struct hisi_thermal_sensor *sensor, static int hisi_thermal_probe(struct platform_device *pdev) { struct hisi_thermal_data *data; - int (*platform_probe)(struct hisi_thermal_data *); struct device *dev = &pdev->dev; - int ret; + struct resource *res; + int i, ret; data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) @@ -537,41 +566,50 @@ static int hisi_thermal_probe(struct platform_device *pdev) data->pdev = pdev; platform_set_drvdata(pdev, data); + data->ops = of_device_get_match_data(dev); - platform_probe = of_device_get_match_data(dev); - if (!platform_probe) { - dev_err(dev, "failed to get probe func\n"); - return -EINVAL; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(data->regs)) { + dev_err(dev, "failed to get io address\n"); + return PTR_ERR(data->regs); } - ret = platform_probe(data); + ret = data->ops->probe(data); if (ret) return ret; - ret = hisi_thermal_register_sensor(pdev, data, - &data->sensor); - if (ret) { - dev_err(dev, "failed to register thermal sensor: %d\n", ret); - return ret; - } + for (i = 0; i < data->nr_sensors; i++) { + struct hisi_thermal_sensor *sensor = &data->sensor[i]; - ret = data->enable_sensor(data); - if (ret) { - dev_err(dev, "Failed to setup the sensor: %d\n", ret); - return ret; - } + ret = hisi_thermal_register_sensor(pdev, sensor); + if (ret) { + dev_err(dev, "failed to register thermal sensor: %d\n", + ret); + return ret; + } + + ret = platform_get_irq_byname(pdev, sensor->irq_name); + if (ret < 0) + return ret; - if (data->irq) { - ret = devm_request_threaded_irq(dev, data->irq, NULL, - hisi_thermal_alarm_irq_thread, - IRQF_ONESHOT, "hisi_thermal", data); + ret = devm_request_threaded_irq(dev, ret, NULL, + hisi_thermal_alarm_irq_thread, + IRQF_ONESHOT, sensor->irq_name, + sensor); if (ret < 0) { - dev_err(dev, "failed to request alarm irq: %d\n", ret); + dev_err(dev, "Failed to request alarm irq: %d\n", ret); return ret; } - } - hisi_thermal_toggle_sensor(&data->sensor, true); + ret = data->ops->enable_sensor(sensor); + if (ret) { + dev_err(dev, "Failed to setup the sensor: %d\n", ret); + return ret; + } + + hisi_thermal_toggle_sensor(sensor, true); + } return 0; } @@ -579,11 +617,14 @@ static int hisi_thermal_probe(struct platform_device *pdev) static int hisi_thermal_remove(struct platform_device *pdev) { struct hisi_thermal_data *data = platform_get_drvdata(pdev); - struct hisi_thermal_sensor *sensor = &data->sensor; + int i; - hisi_thermal_toggle_sensor(sensor, false); + for (i = 0; i < data->nr_sensors; i++) { + struct hisi_thermal_sensor *sensor = &data->sensor[i]; - data->disable_sensor(data); + hisi_thermal_toggle_sensor(sensor, false); + data->ops->disable_sensor(sensor); + } return 0; } @@ -592,8 +633,10 @@ static int hisi_thermal_remove(struct platform_device *pdev) static int hisi_thermal_suspend(struct device *dev) { struct hisi_thermal_data *data = dev_get_drvdata(dev); + int i; - data->disable_sensor(data); + for (i = 0; i < data->nr_sensors; i++) + data->ops->disable_sensor(&data->sensor[i]); return 0; } @@ -601,8 +644,12 @@ static int hisi_thermal_suspend(struct device *dev) static int hisi_thermal_resume(struct device *dev) { struct hisi_thermal_data *data = dev_get_drvdata(dev); + int i, ret = 0; + + for (i = 0; i < data->nr_sensors; i++) + ret |= data->ops->enable_sensor(&data->sensor[i]); - return data->enable_sensor(data); + return ret; } #endif diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c index aa452acb60b6..15661549eb67 100644 --- a/drivers/thermal/imx_thermal.c +++ b/drivers/thermal/imx_thermal.c @@ -725,7 +725,7 @@ static int imx_thermal_probe(struct platform_device *pdev) } else { ret = imx_init_from_tempmon_data(pdev); if (ret) { - dev_err(&pdev->dev, "failed to init from from fsl,tempmon-data\n"); + dev_err(&pdev->dev, "failed to init from fsl,tempmon-data\n"); return ret; } } @@ -762,9 +762,7 @@ static int imx_thermal_probe(struct platform_device *pdev) if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "failed to get thermal clk: %d\n", ret); - cpufreq_cooling_unregister(data->cdev); - cpufreq_cpu_put(data->policy); - return ret; + goto cpufreq_put; } /* @@ -777,9 +775,7 @@ static int imx_thermal_probe(struct platform_device *pdev) ret = clk_prepare_enable(data->thermal_clk); if (ret) { dev_err(&pdev->dev, "failed to enable thermal clk: %d\n", ret); - cpufreq_cooling_unregister(data->cdev); - cpufreq_cpu_put(data->policy); - return ret; + goto cpufreq_put; } data->tz = thermal_zone_device_register("imx_thermal_zone", @@ -792,10 +788,7 @@ static int imx_thermal_probe(struct platform_device *pdev) ret = PTR_ERR(data->tz); dev_err(&pdev->dev, "failed to register thermal zone device %d\n", ret); - clk_disable_unprepare(data->thermal_clk); - cpufreq_cooling_unregister(data->cdev); - cpufreq_cpu_put(data->policy); - return ret; + goto clk_disable; } dev_info(&pdev->dev, "%s CPU temperature grade - max:%dC" @@ -827,14 +820,20 @@ static int imx_thermal_probe(struct platform_device *pdev) 0, "imx_thermal", data); if (ret < 0) { dev_err(&pdev->dev, "failed to request alarm irq: %d\n", ret); - clk_disable_unprepare(data->thermal_clk); - thermal_zone_device_unregister(data->tz); - cpufreq_cooling_unregister(data->cdev); - cpufreq_cpu_put(data->policy); - return ret; + goto thermal_zone_unregister; } return 0; + +thermal_zone_unregister: + thermal_zone_device_unregister(data->tz); +clk_disable: + clk_disable_unprepare(data->thermal_clk); +cpufreq_put: + cpufreq_cooling_unregister(data->cdev); + cpufreq_cpu_put(data->policy); + + return ret; } static int imx_thermal_remove(struct platform_device *pdev) diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c index 4f2816559205..4bfdb4a1e47d 100644 --- a/drivers/thermal/of-thermal.c +++ b/drivers/thermal/of-thermal.c @@ -19,23 +19,34 @@ /*** Private data structures to represent thermal device tree data ***/ /** - * struct __thermal_bind_param - a match between trip and cooling device + * struct __thermal_cooling_bind_param - a cooling device for a trip point * @cooling_device: a pointer to identify the referred cooling device - * @trip_id: the trip point index - * @usage: the percentage (from 0 to 100) of cooling contribution * @min: minimum cooling state used at this trip point * @max: maximum cooling state used at this trip point */ -struct __thermal_bind_params { +struct __thermal_cooling_bind_param { struct device_node *cooling_device; - unsigned int trip_id; - unsigned int usage; unsigned long min; unsigned long max; }; /** + * struct __thermal_bind_param - a match between trip and cooling device + * @tcbp: a pointer to an array of cooling devices + * @count: number of elements in array + * @trip_id: the trip point index + * @usage: the percentage (from 0 to 100) of cooling contribution + */ + +struct __thermal_bind_params { + struct __thermal_cooling_bind_param *tcbp; + unsigned int count; + unsigned int trip_id; + unsigned int usage; +}; + +/** * struct __thermal_zone - internal representation of a thermal zone * @mode: current thermal zone device mode (enabled/disabled) * @passive_delay: polling interval while passive cooling is activated @@ -192,25 +203,31 @@ static int of_thermal_bind(struct thermal_zone_device *thermal, struct thermal_cooling_device *cdev) { struct __thermal_zone *data = thermal->devdata; - int i; + struct __thermal_bind_params *tbp; + struct __thermal_cooling_bind_param *tcbp; + int i, j; if (!data || IS_ERR(data)) return -ENODEV; /* find where to bind */ for (i = 0; i < data->num_tbps; i++) { - struct __thermal_bind_params *tbp = data->tbps + i; + tbp = data->tbps + i; - if (tbp->cooling_device == cdev->np) { - int ret; + for (j = 0; j < tbp->count; j++) { + tcbp = tbp->tcbp + j; - ret = thermal_zone_bind_cooling_device(thermal, + if (tcbp->cooling_device == cdev->np) { + int ret; + + ret = thermal_zone_bind_cooling_device(thermal, tbp->trip_id, cdev, - tbp->max, - tbp->min, + tcbp->max, + tcbp->min, tbp->usage); - if (ret) - return ret; + if (ret) + return ret; + } } } @@ -221,22 +238,28 @@ static int of_thermal_unbind(struct thermal_zone_device *thermal, struct thermal_cooling_device *cdev) { struct __thermal_zone *data = thermal->devdata; - int i; + struct __thermal_bind_params *tbp; + struct __thermal_cooling_bind_param *tcbp; + int i, j; if (!data || IS_ERR(data)) return -ENODEV; /* find where to unbind */ for (i = 0; i < data->num_tbps; i++) { - struct __thermal_bind_params *tbp = data->tbps + i; + tbp = data->tbps + i; + + for (j = 0; j < tbp->count; j++) { + tcbp = tbp->tcbp + j; - if (tbp->cooling_device == cdev->np) { - int ret; + if (tcbp->cooling_device == cdev->np) { + int ret; - ret = thermal_zone_unbind_cooling_device(thermal, - tbp->trip_id, cdev); - if (ret) - return ret; + ret = thermal_zone_unbind_cooling_device(thermal, + tbp->trip_id, cdev); + if (ret) + return ret; + } } } @@ -486,8 +509,8 @@ thermal_zone_of_sensor_register(struct device *dev, int sensor_id, void *data, if (sensor_specs.args_count >= 1) { id = sensor_specs.args[0]; WARN(sensor_specs.args_count > 1, - "%s: too many cells in sensor specifier %d\n", - sensor_specs.np->name, sensor_specs.args_count); + "%pOFn: too many cells in sensor specifier %d\n", + sensor_specs.np, sensor_specs.args_count); } else { id = 0; } @@ -655,8 +678,9 @@ static int thermal_of_populate_bind_params(struct device_node *np, int ntrips) { struct of_phandle_args cooling_spec; + struct __thermal_cooling_bind_param *__tcbp; struct device_node *trip; - int ret, i; + int ret, i, count; u32 prop; /* Default weight. Usage is optional */ @@ -683,20 +707,44 @@ static int thermal_of_populate_bind_params(struct device_node *np, goto end; } - ret = of_parse_phandle_with_args(np, "cooling-device", "#cooling-cells", - 0, &cooling_spec); - if (ret < 0) { - pr_err("missing cooling_device property\n"); + count = of_count_phandle_with_args(np, "cooling-device", + "#cooling-cells"); + if (!count) { + pr_err("Add a cooling_device property with at least one device\n"); goto end; } - __tbp->cooling_device = cooling_spec.np; - if (cooling_spec.args_count >= 2) { /* at least min and max */ - __tbp->min = cooling_spec.args[0]; - __tbp->max = cooling_spec.args[1]; - } else { - pr_err("wrong reference to cooling device, missing limits\n"); + + __tcbp = kcalloc(count, sizeof(*__tcbp), GFP_KERNEL); + if (!__tcbp) + goto end; + + for (i = 0; i < count; i++) { + ret = of_parse_phandle_with_args(np, "cooling-device", + "#cooling-cells", i, &cooling_spec); + if (ret < 0) { + pr_err("Invalid cooling-device entry\n"); + goto free_tcbp; + } + + __tcbp[i].cooling_device = cooling_spec.np; + + if (cooling_spec.args_count >= 2) { /* at least min and max */ + __tcbp[i].min = cooling_spec.args[0]; + __tcbp[i].max = cooling_spec.args[1]; + } else { + pr_err("wrong reference to cooling device, missing limits\n"); + } } + __tbp->tcbp = __tcbp; + __tbp->count = count; + + goto end; + +free_tcbp: + for (i = i - 1; i >= 0; i--) + of_node_put(__tcbp[i].cooling_device); + kfree(__tcbp); end: of_node_put(trip); @@ -903,8 +951,16 @@ finish: return tz; free_tbps: - for (i = i - 1; i >= 0; i--) - of_node_put(tz->tbps[i].cooling_device); + for (i = i - 1; i >= 0; i--) { + struct __thermal_bind_params *tbp = tz->tbps + i; + int j; + + for (j = 0; j < tbp->count; j++) + of_node_put(tbp->tcbp[j].cooling_device); + + kfree(tbp->tcbp); + } + kfree(tz->tbps); free_trips: for (i = 0; i < tz->ntrips; i++) @@ -920,10 +976,18 @@ free_tz: static inline void of_thermal_free_zone(struct __thermal_zone *tz) { - int i; + struct __thermal_bind_params *tbp; + int i, j; + + for (i = 0; i < tz->num_tbps; i++) { + tbp = tz->tbps + i; + + for (j = 0; j < tbp->count; j++) + of_node_put(tbp->tcbp[j].cooling_device); + + kfree(tbp->tcbp); + } - for (i = 0; i < tz->num_tbps; i++) - of_node_put(tz->tbps[i].cooling_device); kfree(tz->tbps); for (i = 0; i < tz->ntrips; i++) of_node_put(tz->trips[i].np); @@ -963,8 +1027,8 @@ int __init of_parse_thermal_zones(void) tz = thermal_of_build_thermal_zone(child); if (IS_ERR(tz)) { - pr_err("failed to build thermal zone %s: %ld\n", - child->name, + pr_err("failed to build thermal zone %pOFn: %ld\n", + child, PTR_ERR(tz)); continue; } @@ -998,7 +1062,7 @@ int __init of_parse_thermal_zones(void) tz->passive_delay, tz->polling_delay); if (IS_ERR(zone)) { - pr_err("Failed to build %s zone %ld\n", child->name, + pr_err("Failed to build %pOFn zone %ld\n", child, PTR_ERR(zone)); kfree(tzp); kfree(ops); diff --git a/drivers/thermal/qcom-spmi-temp-alarm.c b/drivers/thermal/qcom-spmi-temp-alarm.c index ad4f3a8d6560..b2d5d5bf4a9b 100644 --- a/drivers/thermal/qcom-spmi-temp-alarm.c |
