From bdda1c74045fd6469f2d0346187c2fa5ea9bda7c Mon Sep 17 00:00:00 2001 From: David Collins Date: Wed, 12 Sep 2012 14:58:54 -0700 Subject: [PATCH] thermal: pm8xxx-tm: Use delayed_work task for temp alarm status reading Use a delayed_work task to wait at least 40 ms in order for the temp alarm status value to be updated after the TEMP_STAT IRQ goes high. Also remove IRQ enable and disable calls in the ISR since the work item can only be enqueued once before it is run. Change-Id: Ib5f13d0e82258b399749de96152c081d71981909 Signed-off-by: David Collins (cherry picked from commit a42ed24bdc1a1ab8e2c0148430df063ee0679d18) --- drivers/thermal/pm8xxx-tm.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/thermal/pm8xxx-tm.c b/drivers/thermal/pm8xxx-tm.c index 8d9ee86bc4b..b068a064dd6 100644 --- a/drivers/thermal/pm8xxx-tm.c +++ b/drivers/thermal/pm8xxx-tm.c @@ -65,7 +65,7 @@ struct pm8xxx_tm_chip { struct pm8xxx_tm_core_data cdata; - struct work_struct irq_work; + struct delayed_work irq_work; struct device *dev; struct thermal_zone_device *tz_dev; unsigned long temp; @@ -83,6 +83,9 @@ enum pmic_thermal_override_mode { SOFTWARE_OVERRIDE_ENABLED, }; +/* Delay between TEMP_STAT IRQ going high and status value changing in ms. */ +#define STATUS_REGISTER_DELAY_MS 40 + static inline int pm8xxx_tm_read_ctrl(struct pm8xxx_tm_chip *chip, u8 *reg) { int rc; @@ -422,8 +425,10 @@ static struct thermal_zone_device_ops pm8xxx_thermal_zone_ops_pm8058_adc = { static void pm8xxx_tm_work(struct work_struct *work) { + struct delayed_work *dwork + = container_of(work, struct delayed_work, work); struct pm8xxx_tm_chip *chip - = container_of(work, struct pm8xxx_tm_chip, irq_work); + = container_of(dwork, struct pm8xxx_tm_chip, irq_work); unsigned long temp = 0; int rc, stage, thresh; u8 reg; @@ -472,17 +477,15 @@ static void pm8xxx_tm_work(struct work_struct *work) } bail: - enable_irq(chip->tempstat_irq); - enable_irq(chip->overtemp_irq); + return; } static irqreturn_t pm8xxx_tm_isr(int irq, void *data) { struct pm8xxx_tm_chip *chip = data; - disable_irq_nosync(chip->tempstat_irq); - disable_irq_nosync(chip->overtemp_irq); - schedule_work(&chip->irq_work); + schedule_delayed_work(&chip->irq_work, + msecs_to_jiffies(STATUS_REGISTER_DELAY_MS) + 1); return IRQ_HANDLED; } @@ -621,7 +624,7 @@ static int __devinit pm8xxx_tm_probe(struct platform_device *pdev) chip->mode = THERMAL_DEVICE_DISABLED; thermal_zone_device_update(chip->tz_dev); - INIT_WORK(&chip->irq_work, pm8xxx_tm_work); + INIT_DELAYED_WORK(&chip->irq_work, pm8xxx_tm_work); rc = request_irq(chip->tempstat_irq, pm8xxx_tm_isr, IRQF_TRIGGER_RISING, chip->cdata.irq_name_temp_stat, chip); @@ -646,7 +649,7 @@ static int __devinit pm8xxx_tm_probe(struct platform_device *pdev) err_free_irq_tempstat: free_irq(chip->tempstat_irq, chip); err_cancel_work: - cancel_work_sync(&chip->irq_work); + cancel_delayed_work_sync(&chip->irq_work); err_free_tz: thermal_zone_device_unregister(chip->tz_dev); err_fail_adc: @@ -662,7 +665,7 @@ static int __devexit pm8xxx_tm_remove(struct platform_device *pdev) if (chip) { platform_set_drvdata(pdev, NULL); - cancel_work_sync(&chip->irq_work); + cancel_delayed_work_sync(&chip->irq_work); free_irq(chip->overtemp_irq, chip); free_irq(chip->tempstat_irq, chip); pm8xxx_tm_shutdown_override(chip, SOFTWARE_OVERRIDE_DISABLED);