diff options
Diffstat (limited to 'drivers/thermal/rcar_thermal.c')
| -rw-r--r-- | drivers/thermal/rcar_thermal.c | 58 |
1 files changed, 37 insertions, 21 deletions
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 2cc5b6115e3..8803e693fe6 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -24,6 +24,7 @@ #include <linux/io.h> #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/pm_runtime.h> #include <linux/reboot.h> #include <linux/slab.h> #include <linux/spinlock.h> @@ -298,12 +299,17 @@ static void _rcar_thermal_irq_ctrl(struct rcar_thermal_priv *priv, int enable) static void rcar_thermal_work(struct work_struct *work) { struct rcar_thermal_priv *priv; + unsigned long cctemp, nctemp; priv = container_of(work, struct rcar_thermal_priv, work.work); + rcar_thermal_get_temp(priv->zone, &cctemp); rcar_thermal_update_temp(priv); rcar_thermal_irq_enable(priv); - thermal_zone_device_update(priv->zone); + + rcar_thermal_get_temp(priv->zone, &nctemp); + if (nctemp != cctemp) + thermal_zone_device_update(priv->zone); } static u32 rcar_thermal_had_changed(struct rcar_thermal_priv *priv, u32 status) @@ -312,7 +318,7 @@ static u32 rcar_thermal_had_changed(struct rcar_thermal_priv *priv, u32 status) status = (status >> rcar_id_to_shift(priv)) & 0x3; - if (status & 0x3) { + if (status) { dev_dbg(dev, "thermal%d %s%s\n", priv->id, (status & 0x2) ? "Rising " : "", @@ -368,15 +374,16 @@ static int rcar_thermal_probe(struct platform_device *pdev) int idle = IDLE_INTERVAL; common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL); - if (!common) { - dev_err(dev, "Could not allocate common\n"); + if (!common) return -ENOMEM; - } INIT_LIST_HEAD(&common->head); spin_lock_init(&common->lock); common->dev = dev; + pm_runtime_enable(dev); + pm_runtime_get_sync(dev); + irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (irq) { int ret; @@ -385,11 +392,6 @@ static int rcar_thermal_probe(struct platform_device *pdev) * platform has IRQ support. * Then, drier use common register */ - res = platform_get_resource(pdev, IORESOURCE_MEM, mres++); - if (!res) { - dev_err(dev, "Could not get platform resource\n"); - return -ENODEV; - } ret = devm_request_irq(dev, irq->start, rcar_thermal_irq, 0, dev_name(dev), common); @@ -401,6 +403,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) /* * rcar_has_irq_support() will be enabled */ + res = platform_get_resource(pdev, IORESOURCE_MEM, mres++); common->base = devm_ioremap_resource(dev, res); if (IS_ERR(common->base)) return PTR_ERR(common->base); @@ -408,7 +411,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) /* enable temperature comparation */ rcar_thermal_common_write(common, ENR, 0x00030303); - idle = 0; /* polling delaye is not needed */ + idle = 0; /* polling delay is not needed */ } for (i = 0;; i++) { @@ -418,13 +421,15 @@ static int rcar_thermal_probe(struct platform_device *pdev) priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) { - dev_err(dev, "Could not allocate priv\n"); - return -ENOMEM; + ret = -ENOMEM; + goto error_unregister; } priv->base = devm_ioremap_resource(dev, res); - if (IS_ERR(priv->base)) - return PTR_ERR(priv->base); + if (IS_ERR(priv->base)) { + ret = PTR_ERR(priv->base); + goto error_unregister; + } priv->common = common; priv->id = i; @@ -443,21 +448,27 @@ static int rcar_thermal_probe(struct platform_device *pdev) goto error_unregister; } - list_move_tail(&priv->list, &common->head); - if (rcar_has_irq_support(priv)) rcar_thermal_irq_enable(priv); + + list_move_tail(&priv->list, &common->head); } platform_set_drvdata(pdev, common); - dev_info(dev, "%d sensor proved\n", i); + dev_info(dev, "%d sensor probed\n", i); return 0; error_unregister: - rcar_thermal_for_each_priv(priv, common) + rcar_thermal_for_each_priv(priv, common) { thermal_zone_device_unregister(priv->zone); + if (rcar_has_irq_support(priv)) + rcar_thermal_irq_disable(priv); + } + + pm_runtime_put(dev); + pm_runtime_disable(dev); return ret; } @@ -465,12 +476,17 @@ error_unregister: static int rcar_thermal_remove(struct platform_device *pdev) { struct rcar_thermal_common *common = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; struct rcar_thermal_priv *priv; - rcar_thermal_for_each_priv(priv, common) + rcar_thermal_for_each_priv(priv, common) { thermal_zone_device_unregister(priv->zone); + if (rcar_has_irq_support(priv)) + rcar_thermal_irq_disable(priv); + } - platform_set_drvdata(pdev, NULL); + pm_runtime_put(dev); + pm_runtime_disable(dev); return 0; } |
