diff options
Diffstat (limited to 'drivers/thermal/rcar_thermal.c')
| -rw-r--r-- | drivers/thermal/rcar_thermal.c | 81 |
1 files changed, 48 insertions, 33 deletions
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 28f09199401..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> @@ -145,6 +146,7 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv) struct device *dev = rcar_priv_to_dev(priv); int i; int ctemp, old, new; + int ret = -EINVAL; mutex_lock(&priv->lock); @@ -174,7 +176,7 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv) if (!ctemp) { dev_err(dev, "thermal sensor was broken\n"); - return -EINVAL; + goto err_out_unlock; } /* @@ -192,10 +194,10 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv) dev_dbg(dev, "thermal%d %d -> %d\n", priv->id, priv->ctemp, ctemp); priv->ctemp = ctemp; - + ret = 0; +err_out_unlock: mutex_unlock(&priv->lock); - - return 0; + return ret; } static int rcar_thermal_get_temp(struct thermal_zone_device *zone, @@ -297,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) @@ -311,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 " : "", @@ -363,18 +370,20 @@ static int rcar_thermal_probe(struct platform_device *pdev) struct resource *res, *irq; int mres = 0; int i; + int ret = -ENODEV; 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; @@ -383,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); @@ -399,16 +403,15 @@ static int rcar_thermal_probe(struct platform_device *pdev) /* * rcar_has_irq_support() will be enabled */ - common->base = devm_request_and_ioremap(dev, res); - if (!common->base) { - dev_err(dev, "Unable to ioremap thermal register\n"); - return -ENOMEM; - } + 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); /* 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,14 +421,14 @@ 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_request_and_ioremap(dev, res); - if (!priv->base) { - dev_err(dev, "Unable to ioremap priv register\n"); - return -ENOMEM; + priv->base = devm_ioremap_resource(dev, res); + if (IS_ERR(priv->base)) { + ret = PTR_ERR(priv->base); + goto error_unregister; } priv->common = common; @@ -441,37 +444,49 @@ static int rcar_thermal_probe(struct platform_device *pdev) idle); if (IS_ERR(priv->zone)) { dev_err(dev, "can't register thermal zone\n"); + ret = PTR_ERR(priv->zone); 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); + } - return -ENODEV; + pm_runtime_put(dev); + pm_runtime_disable(dev); + + return ret; } 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; } |
