From 850722c4426edd302ff6c6364f3f0703e7a4d109 Mon Sep 17 00:00:00 2001 From: root Date: Tue, 24 May 2011 09:11:45 +0800 Subject: [PATCH] 1. return -1 if read voltage error before reporting battery's event; 2. change to use delay workqueue to wait spi resume; 3. delete flush(dws) operation from spi resume function to avoid spi error while system resume; 4. delete suspend_noirq function from wm831x_on.c to avoid reading spi before spim resume; 5. add touchscreen delay to 200us to avoid i2c error; --- drivers/input/misc/wm831x-on.c | 5 ++-- drivers/input/touchscreen/ili2102_ts.c | 27 +++++++++++++-------- drivers/mfd/wm831x-irq.c | 21 ++++++++++++---- drivers/mfd/wm831x-spi.c | 10 ++++---- drivers/power/wm831x_power.c | 33 +++++++++++++++++++++----- drivers/spi/rk29_spim.c | 6 +++-- include/linux/mfd/wm831x/core.h | 4 +++- 7 files changed, 77 insertions(+), 29 deletions(-) diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c index 3cc51bb26a15..3d1787ac4410 100755 --- a/drivers/input/misc/wm831x-on.c +++ b/drivers/input/misc/wm831x-on.c @@ -63,7 +63,7 @@ void rk28_send_wakeup_key(void) } #endif -#if 1 +#if 0 static int wm831x_on_suspend_noirq(struct device *dev) { @@ -89,6 +89,7 @@ static int wm831x_on_resume_noirq(struct device *dev) input_sync(g_wm831x_on->dev); DBG("%s:poll=%d,ret=0x%x\n",__FUNCTION__,poll,ret); } + DBG("%s\n",__FUNCTION__); return 0; } @@ -229,7 +230,7 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev) wm831x_on->dev->dev.parent = &pdev->dev; g_wm831x_on = wm831x_on; - wm831x_on_pm_init(); +// wm831x_on_pm_init(); ret = request_threaded_irq(irq, NULL, wm831x_on_irq, IRQF_TRIGGER_RISING, "wm831x_on", diff --git a/drivers/input/touchscreen/ili2102_ts.c b/drivers/input/touchscreen/ili2102_ts.c index 57a6fd2bc334..8058fffce2e6 100755 --- a/drivers/input/touchscreen/ili2102_ts.c +++ b/drivers/input/touchscreen/ili2102_ts.c @@ -313,20 +313,27 @@ static void ili2102_ts_work_func(struct work_struct *work) msg[0].len = 1; msg[0].buf = &start_reg; msg[0].scl_rate = 400*1000; - msg[0].udelay = 80; + msg[0].udelay = 0; - msg[1].addr = ts->client->addr; - msg[1].flags = ts->client->flags | I2C_M_RD; - msg[1].len = 9; - msg[1].buf = buf; - msg[1].scl_rate = 400*1000; - msg[1].udelay = 80; + ret = i2c_transfer(ts->client->adapter, msg, 1); + if (ret < 0) + { + printk("%s:i2c_transfer fail, ret=%d\n",__FUNCTION__,ret); + goto out; + } + + udelay(200); //tp need delay + + msg[0].addr = ts->client->addr; + msg[0].flags = ts->client->flags | I2C_M_RD; + msg[0].len = 9; + msg[0].buf = buf; + msg[0].scl_rate = 400*1000; + msg[0].udelay = 0; - ret = i2c_transfer(ts->client->adapter, msg, 2); + ret = i2c_transfer(ts->client->adapter, msg, 1); if (ret < 0) { - //for(i=0; idev, "Failed to read system interrupt: %d\n", @@ -607,14 +608,25 @@ out: static irqreturn_t wm831x_irq_thread(int irq, void *data) { struct wm831x *wm831x = data; - + int msdelay = 0; /* Shut the interrupt to the CPU up and schedule the actual * handler; we can't check that the IRQ is asserted. */ #if (WM831X_IRQ_TYPE == IRQF_TRIGGER_LOW) disable_irq_nosync(irq); #endif wake_lock(&wm831x->irq_wake); - queue_work(wm831x->irq_wq, &wm831x->irq_work); + if(wm831x->flag_suspend) + { + spin_lock(&wm831x->flag_lock); + wm831x->flag_suspend = 0; + spin_unlock(&wm831x->flag_lock); + msdelay = 50; //wait for spi/i2c resume + printk("%s:msdelay=%d\n",__FUNCTION__,msdelay); + } + else + msdelay = 0; + + queue_delayed_work(wm831x->irq_wq, &wm831x->irq_work, msecs_to_jiffies(msdelay)); //printk("%s\n",__FUNCTION__); return IRQ_HANDLED; } @@ -654,8 +666,9 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq) wm831x->irq = irq; + wm831x->flag_suspend = 0; wm831x->irq_base = pdata->irq_base; - INIT_WORK(&wm831x->irq_work, wm831x_irq_worker); + INIT_DELAYED_WORK(&wm831x->irq_work, wm831x_irq_worker); wake_lock_init(&wm831x->irq_wake, WAKE_LOCK_SUSPEND, "wm831x_irq_wake"); wake_lock_init(&wm831x->handle_wake, WAKE_LOCK_SUSPEND, "wm831x_handle_wake"); #if WM831X_IRQ_LIST diff --git a/drivers/mfd/wm831x-spi.c b/drivers/mfd/wm831x-spi.c index 1fe4de7d86e6..e0032b9b2a05 100755 --- a/drivers/mfd/wm831x-spi.c +++ b/drivers/mfd/wm831x-spi.c @@ -30,12 +30,12 @@ static int wm831x_spi_read_device(struct wm831x *wm831x, unsigned short reg, /* Go register at a time */ for (r = reg; r < reg + (bytes / 2); r++) { tx_val = cpu_to_be16(r | 0x8000); - + //printk("read:reg=0x%x,",reg); ret = spi_write_then_read(wm831x->control_data, (u8 *)&tx_val, 2, (u8 *)d, 2); if (ret != 0) return ret; - + //printk("rec=0x%x\n",be16_to_cpu(*d)); //*d = be16_to_cpu(*d); d++; @@ -56,7 +56,7 @@ static int wm831x_spi_write_device(struct wm831x *wm831x, unsigned short reg, for (r = reg; r < reg + (bytes / 2); r++) { data[0] = cpu_to_be16(r); data[1] = *s++; - + //printk("write:reg=0x%x,send=0x%x\n",reg, data[0]); ret = spi_write(spi, (char *)&data, sizeof(data)); if (ret != 0) return ret; @@ -130,7 +130,9 @@ static int __devexit wm831x_spi_remove(struct spi_device *spi) static int wm831x_spi_suspend(struct spi_device *spi, pm_message_t m) { struct wm831x *wm831x = dev_get_drvdata(&spi->dev); - + spin_lock(&wm831x->flag_lock); + wm831x->flag_suspend = 1; + spin_unlock(&wm831x->flag_lock); return wm831x_device_suspend(wm831x); } diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c index a31225d30584..2a5aa5698824 100755 --- a/drivers/power/wm831x_power.c +++ b/drivers/power/wm831x_power.c @@ -777,12 +777,31 @@ static void wm831x_batt_work(struct work_struct *work) struct wm831x_power *power = container_of(work, struct wm831x_power, batt_work); ret = wm831x_power_check_online(power->wm831x, WM831X_PWR_SRC_BATT, &val); + if (ret < 0) { + printk("%s: check bat online failer... err = %d\n", __FUNCTION__, ret); + return; + } online = val.intval; ret = wm831x_bat_check_status(power->wm831x, &status); + if (ret < 0) { + printk("%s: check bat status failer... err = %d\n", __FUNCTION__, ret); + return; + } + ret = wm831x_bat_check_health(power->wm831x, &health); + if (ret < 0) { + printk("%s: check bat health failer... err = %d\n", __FUNCTION__, ret); + return; + } ret = wm831x_power_read_voltage(power->wm831x, WM831X_AUX_BATT, &val); + if (ret < 0) { + printk("%s: read bat voltage failer...err = %d\n", __FUNCTION__, ret); + return; + } + power->priv.voltage = val.intval; + wm831x_batt_vol_level(power, val.intval, &level); mod_timer(&power->timer, jiffies + msecs_to_jiffies(power->interval)); @@ -943,17 +962,19 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev) #ifdef CONFIG_PM static int wm831x_battery_suspend(struct platform_device *dev, pm_message_t state) { - //struct wm831x_power *power = (struct wm831x_power *)platform_get_drvdata(dev); - //flush_scheduled_work(); - //del_timer(&power->timer); + struct wm831x_power *power = (struct wm831x_power *)platform_get_drvdata(dev); + flush_scheduled_work(); + del_timer(&power->timer); + printk("%s\n",__FUNCTION__); return 0; } static int wm831x_battery_resume(struct platform_device *dev) { - //struct wm831x_power *power = (struct wm831x_power *)platform_get_drvdata(dev); - //power->timer.expires = jiffies + msecs_to_jiffies(power->interval); - //add_timer(&power->timer); + struct wm831x_power *power = (struct wm831x_power *)platform_get_drvdata(dev); + power->timer.expires = jiffies + msecs_to_jiffies(power->interval); + add_timer(&power->timer); + printk("%s\n",__FUNCTION__); return 0; } #else diff --git a/drivers/spi/rk29_spim.c b/drivers/spi/rk29_spim.c index bb8b2ae76ed0..874dffb15d02 100755 --- a/drivers/spi/rk29_spim.c +++ b/drivers/spi/rk29_spim.c @@ -1766,7 +1766,7 @@ static void spi_hw_init(struct rk29xx_spi *dws) } spi_enable_chip(dws, 1); - flush(dws); + //flush(dws); } /* cpufreq driver support */ @@ -1893,6 +1893,7 @@ static int __init rk29xx_spim_probe(struct platform_device *pdev) dws->pdev = pdev; /* Basic HW init */ spi_hw_init(dws); + flush(dws); /* Initial and start queue */ ret = init_queue(dws); if (ret) { @@ -1973,7 +1974,8 @@ static int rk29xx_spim_suspend(struct platform_device *pdev, pm_message_t mesg) struct rk29xx_spi *dws = spi_master_get_devdata(master); struct rk29xx_spi_platform_data *pdata = pdev->dev.platform_data; int status; - + + flush(dws); status = stop_queue(dws); if (status != 0) return status; diff --git a/include/linux/mfd/wm831x/core.h b/include/linux/mfd/wm831x/core.h index fb21267f0267..22a41d1a25d0 100755 --- a/include/linux/mfd/wm831x/core.h +++ b/include/linux/mfd/wm831x/core.h @@ -261,9 +261,11 @@ struct wm831x { void *control_data; int irq; /* Our chip IRQ */ + int flag_suspend; + spinlock_t flag_lock; struct mutex irq_lock; struct workqueue_struct *irq_wq; - struct work_struct irq_work; + struct delayed_work irq_work; struct wake_lock irq_wake; struct wake_lock handle_wake; #if WM831X_IRQ_LIST -- 2.34.1