update DRV2625 driver to better support non-interrupt service applications
authorPeter Li <peter-li@ti.com>
Sun, 12 Mar 2017 01:18:18 +0000 (09:18 +0800)
committerPeter Li <peter-li@ti.com>
Sun, 12 Mar 2017 01:18:18 +0000 (09:18 +0800)
drv2625.c
drv2625.h

index 215568cf055547ac8a57c8fb553ab6220700a05c..fab861c2e0b3e9ea63703dff4d2e636920cf03f0 100755 (executable)
--- a/drv2625.c
+++ b/drv2625.c
@@ -36,7 +36,7 @@
 #include <linux/semaphore.h>
 #include <linux/device.h>
 #include <linux/syscalls.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/gpio.h>
 #include <linux/sched.h>
 #include <linux/spinlock_types.h>
 #include <linux/miscdevice.h>
 #include "drv2625.h"
 
-//#define      AUTOCALIBRATION_ENABLE
-
 static struct drv2625_data *g_DRV2625data = NULL;
+static bool g_logEnable = false;
 
-static int drv2625_reg_read(struct drv2625_data *pDRV2625, unsigned char reg)
+static int drv2625_reg_read(struct drv2625_data *pDRV2625,
+       unsigned char reg)
 {
        unsigned int val;
-       int ret;
-       
-       ret = regmap_read(pDRV2625->mpRegmap, reg, &val);
-    
-       if (ret < 0){
-               dev_err(pDRV2625->dev, 
-                       "%s reg=0x%x error %d\n", __FUNCTION__, reg, ret);
-               return ret;
-       }else{
-               dev_dbg(pDRV2625->dev, "%s, Reg[0x%x]=0x%x\n", 
-                       __FUNCTION__, reg, val);
+       int nResult;
+
+       mutex_lock(&pDRV2625->dev_lock);
+       nResult = regmap_read(pDRV2625->mpRegmap, reg, &val);
+    mutex_unlock(&pDRV2625->dev_lock);
+
+       if (nResult < 0) {
+               dev_err(pDRV2625->dev, "%s I2C error %d\n", __func__, nResult);
+               return nResult;
+       } else {
+               if (g_logEnable)
+                       dev_dbg(pDRV2625->dev, "%s, Reg[0x%x]=0x%x\n", __func__, reg, val);
                return val;
        }
 }
 
-static int drv2625_reg_write(struct drv2625_data *pDRV2625, 
+static int drv2625_reg_write(struct drv2625_data *pDRV2625,
        unsigned char reg, unsigned char val)
 {
-       int ret;
-       
-       ret = regmap_write(pDRV2625->mpRegmap, reg, val);
-       if (ret < 0){
-               dev_err(pDRV2625->dev, 
-                       "%s reg=0x%x, value=0%x error %d\n", 
-                       __FUNCTION__, reg, val, ret);
-       }else{
-               dev_dbg(pDRV2625->dev, "%s, Reg[0x%x]=0x%x\n", 
-                       __FUNCTION__, reg, val);
-       }
-       
-       return ret;
+       int nResult;
+
+       mutex_lock(&pDRV2625->dev_lock);
+       nResult = regmap_write(pDRV2625->mpRegmap, reg, val);
+       mutex_unlock(&pDRV2625->dev_lock);
+       if (nResult < 0)
+               dev_err(pDRV2625->dev, "%s reg=0x%x, value=0%x error %d\n",
+                       __func__, reg, val, nResult);
+       else if (g_logEnable)
+               dev_dbg(pDRV2625->dev, "%s, Reg[0x%x]=0x%x\n", __func__, reg, val);
+
+       return nResult;
 }
 
-static int drv2625_bulk_read(struct drv2625_data *pDRV2625, 
-       unsigned char reg, u8 *buf, unsigned int count)
+static int drv2625_bulk_read(struct drv2625_data *pDRV2625,
+       unsigned char reg, unsigned char *buf, unsigned int count)
 {
-       int ret;
-       ret = regmap_bulk_read(pDRV2625->mpRegmap, reg, buf, count);
-       if (ret < 0){
-               dev_err(pDRV2625->dev, 
-                       "%s reg=0%x, count=%d error %d\n", 
-                       __FUNCTION__, reg, count, ret);
-       }
-       
-       return ret;
+       int nResult;
+
+       mutex_lock(&pDRV2625->dev_lock);
+       nResult = regmap_bulk_read(pDRV2625->mpRegmap, reg, buf, count);
+       mutex_unlock(&pDRV2625->dev_lock);
+       if (nResult < 0)
+               dev_err(pDRV2625->dev, "%s reg=0%x, count=%d error %d\n",
+                       __func__, reg, count, nResult);
+
+       return nResult;
 }
 
-static int drv2625_bulk_write(struct drv2625_data *pDRV2625, 
+static int drv2625_bulk_write(struct drv2625_data *pDRV2625,
        unsigned char reg, const u8 *buf, unsigned int count)
 {
-       int ret, i;
-       ret = regmap_bulk_write(pDRV2625->mpRegmap, reg, buf, count);
-       if (ret < 0){
-               dev_err(pDRV2625->dev, 
-                       "%s reg=0%x, count=%d error %d\n", 
-                       __FUNCTION__, reg, count, ret);
-       }else{
+       int nResult, i;
+
+       mutex_lock(&pDRV2625->dev_lock);
+       nResult = regmap_bulk_write(pDRV2625->mpRegmap, reg, buf, count);
+       mutex_unlock(&pDRV2625->dev_lock);
+       if (nResult < 0)
+               dev_err(pDRV2625->dev, "%s reg=0%x, count=%d error %d\n",
+                       __func__, reg, count, nResult);
+       else if (g_logEnable)
                for(i = 0; i < count; i++)
-                       dev_dbg(pDRV2625->dev, "%s, Reg[0x%x]=0x%x\n", 
-                               __FUNCTION__,reg+i, buf[i]);
-       }
-       return ret;     
+                       dev_dbg(pDRV2625->dev, "%s, Reg[0x%x]=0x%x\n",
+                               __func__, reg+i, buf[i]);
+
+       return nResult;
 }
 
-static int drv2625_set_bits(struct drv2625_data *pDRV2625, 
+static int drv2625_set_bits(struct drv2625_data *pDRV2625,
        unsigned char reg, unsigned char mask, unsigned char val)
 {
-       int ret;
-       ret = regmap_update_bits(pDRV2625->mpRegmap, reg, mask, val);
-       if (ret < 0){
-               dev_err(pDRV2625->dev, 
-                       "%s reg=%x, mask=0x%x, value=0x%x error %d\n", 
-                       __FUNCTION__, reg, mask, val, ret);
-       }else{
-               dev_dbg(pDRV2625->dev, "%s, Reg[0x%x]:M=0x%x, V=0x%x\n", 
-                       __FUNCTION__, reg, mask, val);
-       }
-       
-       return ret;     
+       int nResult;
+
+       mutex_lock(&pDRV2625->dev_lock);
+       nResult = regmap_update_bits(pDRV2625->mpRegmap, reg, mask, val);
+       mutex_unlock(&pDRV2625->dev_lock);
+       if (nResult < 0)
+               dev_err(pDRV2625->dev, "%s reg=%x, mask=0x%x, value=0x%x error %d\n",
+                       __func__, reg, mask, val, nResult);
+       else if (g_logEnable)
+               dev_dbg(pDRV2625->dev, "%s, Reg[0x%x]:M=0x%x, V=0x%x\n",
+                       __func__, reg, mask, val);
+
+       return nResult;
 }
 
-static void drv2625_enableIRQ(struct drv2625_data *pDRV2625, unsigned char bRTP)
+static int drv2625_enableIRQ(struct drv2625_data *pDRV2625, unsigned char bRTP)
 {
+       int nResult = 0;
        unsigned char mask = INT_ENABLE_CRITICAL;
-       
-       if(bRTP == 0){
+
+       if (!pDRV2625->mbIRQUsed)
+               goto end;
+
+       if (pDRV2625->mbIRQEnabled)
+               goto end;
+
+       if (bRTP == 0)
                mask = INT_ENABLE_ALL;
-       }
-       
-       drv2625_reg_read(pDRV2625,DRV2625_REG_STATUS);  
-       drv2625_reg_write(pDRV2625, DRV2625_REG_INT_ENABLE, mask);
+
+       nResult = drv2625_reg_read(pDRV2625,DRV2625_REG_STATUS);
+       if (nResult < 0)
+               goto end;
+       nResult = drv2625_reg_write(pDRV2625, DRV2625_REG_INT_ENABLE, mask);
+       if (nResult < 0)
+               goto end;
+
        enable_irq(pDRV2625->mnIRQ);
+       pDRV2625->mbIRQEnabled = true;
+
+end:
+
+       return nResult;
 }
 
 static void drv2625_disableIRQ(struct drv2625_data *pDRV2625)
 {
-       disable_irq(pDRV2625->mnIRQ);
-       drv2625_reg_write(pDRV2625, DRV2625_REG_INT_ENABLE, INT_MASK_ALL);
+       if (pDRV2625->mbIRQUsed) {
+               if (pDRV2625->mbIRQEnabled) {
+                       disable_irq_nosync(pDRV2625->mnIRQ);
+                       drv2625_reg_write(pDRV2625, DRV2625_REG_INT_ENABLE, INT_MASK_ALL);
+                       pDRV2625->mbIRQEnabled = false;
+               }
+       }
 }
 
 static int drv2625_set_go_bit(struct drv2625_data *pDRV2625, unsigned char val)
 {
-       int ret = 0, value =0;
-       int retry = 10; // to finish auto-brake
-       
-       val &= 0x01;    
-       ret = drv2625_reg_write(pDRV2625, DRV2625_REG_GO, val);
-       if(ret >= 0 ){          
-               if(val == 1){
-                       mdelay(1);
+       int nResult = 0, value =0;
+       int retry = POLL_GO_BIT_RETRY; 
+
+       val &= 0x01;
+       nResult = drv2625_reg_write(pDRV2625, DRV2625_REG_GO, val);
+       if (nResult < 0) 
+               goto end;
+
+       mdelay(POLL_GO_BIT_INTERVAL);
+       value = drv2625_reg_read(pDRV2625, DRV2625_REG_GO);
+       if (value < 0) {
+               nResult = value;
+               goto end;
+       }
+
+       if (val) {
+               if (value != GO) {
+                       nResult = -EIO;
+                       dev_warn(pDRV2625->dev, "%s, GO fail, stop action\n", __func__);
+               }
+       } else {
+               while (retry > 0) {
                        value = drv2625_reg_read(pDRV2625, DRV2625_REG_GO);
-                       if(value < 0){
-                               ret = value;
-                       }else if(value != 1){
-                               ret = -1;
-                               dev_warn(pDRV2625->dev, 
-                                       "%s, GO fail, stop action\n", __FUNCTION__);
-                       }
-               }else{
-                       while(retry > 0){
-                               value = drv2625_reg_read(pDRV2625, DRV2625_REG_GO);
-                               if(value < 0){
-                                       ret = value;
-                                       break;
-                               }
-                               
-                               if(value==0) break;
-                               mdelay(10);
-                               retry--;                                
-                       }       
-                       
-                       if(retry == 0){
-                               dev_err(pDRV2625->dev, 
-                                       "%s, ERROR: clear GO fail\n", __FUNCTION__);
+                       if (value < 0) {
+                               nResult = value;
+                               break;
                        }
+
+                       if(value==0)
+                               break;
+
+                       mdelay(POLL_GO_BIT_INTERVAL);
+                       retry--;
                }
+
+               if (retry == 0)
+                       dev_err(pDRV2625->dev,
+                               "%s, ERROR: clear GO fail\n", __func__);
+               else if (g_logEnable)
+                       dev_dbg(pDRV2625->dev,
+                               "%s, clear GO, remain=%d\n", __func__, retry);
        }
-               
-       return ret;
+
+end:
+
+       return nResult;
 }
 
-static void drv2625_change_mode(struct drv2625_data *pDRV2625, unsigned char work_mode)
+static int drv2625_change_mode(struct drv2625_data *pDRV2625,
+       unsigned char work_mode)
 {
-       drv2625_set_bits(pDRV2625, DRV2625_REG_MODE, WORKMODE_MASK , work_mode);
+       return drv2625_set_bits(pDRV2625,
+                       DRV2625_REG_MODE, WORKMODE_MASK, work_mode);
 }
 
 static int vibrator_get_time(struct timed_output_dev *dev)
 {
        struct drv2625_data *pDRV2625 = container_of(dev, struct drv2625_data, to_dev);
 
-    if (hrtimer_active(&pDRV2625->timer)) {
-        ktime_t r = hrtimer_get_remaining(&pDRV2625->timer);
-        return ktime_to_ms(r);
-    }
+       if (hrtimer_active(&pDRV2625->timer)) {
+               ktime_t r = hrtimer_get_remaining(&pDRV2625->timer);
+               return ktime_to_ms(r);
+       }
 
-    return 0;
+       return 0;
 }
 
-static void drv2625_stop(struct drv2625_data *pDRV2625)
+static void drv2625_set_stopflag(struct drv2625_data *pDRV2625)
 {
-       if(pDRV2625->mnVibratorPlaying == YES){
-               dev_dbg(pDRV2625->dev, "%s\n", __FUNCTION__);
-               drv2625_disableIRQ(pDRV2625);
-               hrtimer_cancel(&pDRV2625->timer);       
-               drv2625_set_go_bit(pDRV2625, STOP);
-               pDRV2625->mnVibratorPlaying = NO;
-               wake_unlock(&pDRV2625->wklock);
+       pDRV2625->mnVibratorPlaying = NO;
+       wake_unlock(&pDRV2625->wklock);
+       if (g_logEnable)
+               dev_dbg(pDRV2625->dev, "wklock unlock");
+}
+
+static int drv2625_get_diag_result(struct drv2625_data *pDRV2625, unsigned char nStatus)
+{
+       int nResult = 0;
+
+       pDRV2625->mDiagResult.mnResult = nStatus;
+       if((nStatus&DIAG_MASK) != DIAG_SUCCESS)
+               dev_err(pDRV2625->dev, "Diagnostic fail\n");
+       else {
+               nResult = drv2625_reg_read(pDRV2625, DRV2625_REG_DIAG_Z);
+               if (nResult < 0)
+                       goto end;
+               pDRV2625->mDiagResult.mnDiagZ = nResult;
+
+               nResult = drv2625_reg_read(pDRV2625, DRV2625_REG_DIAG_K);
+               if (nResult < 0)
+                       goto end;
+               pDRV2625->mDiagResult.mnDiagK = nResult;
+
+               dev_dbg(pDRV2625->dev, "Diag : ZResult=0x%x, CurrentK=0x%x\n",
+                       pDRV2625->mDiagResult.mnDiagZ,
+                       pDRV2625->mDiagResult.mnDiagK);
+       }
+
+end:
+       return nResult;
+}
+
+static int drv2625_get_calibration_result(struct drv2625_data *pDRV2625, unsigned char nStatus)
+{
+       int nResult = 0;
+
+       pDRV2625->mAutoCalResult.mnResult = nStatus;
+       if ((nStatus&DIAG_MASK) != DIAG_SUCCESS)
+               dev_err(pDRV2625->dev, "Calibration fail\n");
+       else {
+               nResult = drv2625_reg_read(pDRV2625, DRV2625_REG_CAL_COMP);
+               if (nResult < 0)
+                       goto end;
+               pDRV2625->mAutoCalResult.mnCalComp = nResult;
+
+               nResult = drv2625_reg_read(pDRV2625, DRV2625_REG_CAL_BEMF);
+               if (nResult < 0)
+                       goto end;
+               pDRV2625->mAutoCalResult.mnCalBemf = nResult;
+
+               nResult = drv2625_reg_read(pDRV2625, DRV2625_REG_CAL_COMP) & BEMFGAIN_MASK;
+               if (nResult < 0)
+                       goto end;
+               pDRV2625->mAutoCalResult.mnCalGain = nResult;
+
+               dev_dbg(pDRV2625->dev, "AutoCal : Comp=0x%x, Bemf=0x%x, Gain=0x%x\n",
+                       pDRV2625->mAutoCalResult.mnCalComp,
+                       pDRV2625->mAutoCalResult.mnCalBemf,
+                       pDRV2625->mAutoCalResult.mnCalGain);
+       }
+end:
+       return nResult;
+}
+
+static int drv2625_stop(struct drv2625_data *pDRV2625)
+{
+       int nResult = 0;
+
+       if (pDRV2625->mnVibratorPlaying == YES) {
+               dev_dbg(pDRV2625->dev, "%s\n", __func__);
+               if (pDRV2625->mbIRQUsed)
+                       drv2625_disableIRQ(pDRV2625);
+               if (hrtimer_active(&pDRV2625->timer))
+                       hrtimer_cancel(&pDRV2625->timer);
+               nResult = drv2625_set_go_bit(pDRV2625, STOP);
+               drv2625_set_stopflag(pDRV2625);
        }
+
+       return nResult;
 }
 
 static void vibrator_enable( struct timed_output_dev *dev, int value)
 {
-       int ret = 0;
+       int nResult = 0;
        struct drv2625_data *pDRV2625 = 
                container_of(dev, struct drv2625_data, to_dev);
-       //int status;
-       
-       dev_dbg(pDRV2625->dev, 
-               "%s, value=%d\n", __FUNCTION__, value);
-               
-    mutex_lock(&pDRV2625->lock);
-       
+
+       dev_dbg(pDRV2625->dev, "%s, value=%d\n", __func__, value);
+
+       mutex_lock(&pDRV2625->lock);
+
        pDRV2625->mnWorkMode = WORK_IDLE;
-       dev_dbg(pDRV2625->dev, 
-               "%s, afer mnWorkMode=0x%x\n", 
-               __FUNCTION__, pDRV2625->mnWorkMode);
-               
+       if (g_logEnable)
+               dev_dbg(pDRV2625->dev, "%s, afer mnWorkMode=0x%x\n", 
+                       __func__, pDRV2625->mnWorkMode);
+
        drv2625_stop(pDRV2625);
 
-    if (value > 0) {
+       if (value > 0) {
                wake_lock(&pDRV2625->wklock);
-       
-               drv2625_change_mode(pDRV2625, MODE_RTP);
-               pDRV2625->mnVibratorPlaying = YES;
-               drv2625_enableIRQ(pDRV2625, YES);       
-               ret = drv2625_set_go_bit(pDRV2625, GO);
-               if(ret <0){
-                       dev_warn(pDRV2625->dev, "Start RTP failed\n");
-                       wake_unlock(&pDRV2625->wklock);
-                       pDRV2625->mnVibratorPlaying = NO;
-                       drv2625_disableIRQ(pDRV2625);
-               }else{
-                       value = (value>MAX_TIMEOUT)?MAX_TIMEOUT:value;
+               if (g_logEnable)
+                       dev_dbg(pDRV2625->dev, "wklock lock");
+
+               nResult = drv2625_change_mode(pDRV2625, MODE_RTP);
+               if (nResult < 0)
+                       goto end;
+
+               nResult = drv2625_set_go_bit(pDRV2625, GO);
+               if (nResult >= 0) {
+                       value = (value > MAX_TIMEOUT) ? MAX_TIMEOUT : value;
+                       pDRV2625->mnWorkMode |= WORK_VIBRATOR;
                        hrtimer_start(&pDRV2625->timer, 
                                ns_to_ktime((u64)value * NSEC_PER_MSEC), HRTIMER_MODE_REL);
+                       pDRV2625->mnVibratorPlaying = YES;
+
+                       if (pDRV2625->mbIRQUsed)
+                               nResult = drv2625_enableIRQ(pDRV2625, YES);
                }
-    }
-       
+       }
+
+end:
+       if (nResult < 0) {
+               wake_unlock(&pDRV2625->wklock);
+               if (g_logEnable)
+                       dev_dbg(pDRV2625->dev, "wklock unlock");
+       }
        mutex_unlock(&pDRV2625->lock);
 }
 
 static enum hrtimer_restart vibrator_timer_func(struct hrtimer *timer)
 {
-       struct drv2625_data *pDRV2625 = 
+       struct drv2625_data *pDRV2625 =
                container_of(timer, struct drv2625_data, timer);
 
-       dev_dbg(pDRV2625->dev, "%s\n", __FUNCTION__);
-       pDRV2625->mnWorkMode |= WORK_VIBRATOR;
+       dev_dbg(pDRV2625->dev, "%s\n", __func__);
        schedule_work(&pDRV2625->vibrator_work);
-    return HRTIMER_NORESTART;
+       return HRTIMER_NORESTART;
 }
 
 static void vibrator_work_routine(struct work_struct *work)
 {
-       struct drv2625_data *pDRV2625 = 
+       struct drv2625_data *pDRV2625 =
                container_of(work, struct drv2625_data, vibrator_work);
        unsigned char mode = MODE_RTP;
        unsigned char status; 
-               
+       int nResult = 0;
+
        mutex_lock(&pDRV2625->lock);
 
-       dev_dbg(pDRV2625->dev, 
-               "%s, afer mnWorkMode=0x%x\n", 
-               __FUNCTION__, pDRV2625->mnWorkMode);
-               
-       if(pDRV2625->mnWorkMode & WORK_IRQ){    
-               pDRV2625->mnIntStatus = drv2625_reg_read(pDRV2625,DRV2625_REG_STATUS);
-               drv2625_disableIRQ(pDRV2625);   
+       if (g_logEnable)
+               dev_dbg(pDRV2625->dev, "%s, afer mnWorkMode=0x%x\n",
+                       __func__, pDRV2625->mnWorkMode);
+
+       if ((pDRV2625->mnWorkMode & WORK_IRQ) && pDRV2625->mbIRQUsed) {
+               nResult = drv2625_reg_read(pDRV2625,DRV2625_REG_STATUS);
+               if (nResult >= 0)
+                       pDRV2625->mnIntStatus = nResult;
+               drv2625_disableIRQ(pDRV2625);
+               if (nResult < 0)
+                       goto err;
+
                status = pDRV2625->mnIntStatus;
-               dev_dbg(pDRV2625->dev, 
-                       "%s, status=0x%x\n", 
-                       __FUNCTION__, pDRV2625->mnIntStatus);
-               
-               if(status & OVERCURRENT_MASK){
-                       dev_err(pDRV2625->dev, 
-                               "ERROR, Over Current detected!!\n");
-               }
-               
-               if(status & OVERTEMPRATURE_MASK){
-                       dev_err(pDRV2625->dev, 
-                               "ERROR, Over Temperature detected!!\n");
-               }
-               
-               if(status & ULVO_MASK){
-                       dev_err(pDRV2625->dev, 
-                               "ERROR, VDD drop observed!!\n");
-               }
+               dev_dbg(pDRV2625->dev, "%s, status=0x%x\n",
+                       __func__, pDRV2625->mnIntStatus);
 
-               if(status & PRG_ERR_MASK){
-                       dev_err(pDRV2625->dev, 
-                               "ERROR, PRG error!!\n");                        
-               }
+               if (status & OVERCURRENT_MASK)
+                       dev_err(pDRV2625->dev, "ERROR, Over Current detected!!\n");
+
+               if (status & OVERTEMPRATURE_MASK)
+                       dev_err(pDRV2625->dev, "ERROR, Over Temperature detected!!\n");
+
+               if (status & ULVO_MASK)
+                       dev_err(pDRV2625->dev, "ERROR, VDD drop observed!!\n");
 
-               if(status & PROCESS_DONE_MASK){
-                       mode = drv2625_reg_read(pDRV2625, DRV2625_REG_MODE) & WORKMODE_MASK;
-                       if(mode == MODE_CALIBRATION){
-                               pDRV2625->mAutoCalResult.mnResult = status;
-                               if((status&DIAG_MASK) != DIAG_SUCCESS){
-                                       dev_err(pDRV2625->dev, "Calibration fail\n");
-                               }else{
-                                       pDRV2625->mAutoCalResult.mnCalComp = 
-                                               drv2625_reg_read(pDRV2625, DRV2625_REG_CAL_COMP);
-                                       pDRV2625->mAutoCalResult.mnCalBemf = 
-                                               drv2625_reg_read(pDRV2625, DRV2625_REG_CAL_BEMF);
-                                       pDRV2625->mAutoCalResult.mnCalGain = 
-                                               drv2625_reg_read(pDRV2625, DRV2625_REG_CAL_COMP) & BEMFGAIN_MASK;
-                                       dev_dbg(pDRV2625->dev, 
-                                               "AutoCal : Comp=0x%x, Bemf=0x%x, Gain=0x%x\n",
-                                               pDRV2625->mAutoCalResult.mnCalComp, 
-                                               pDRV2625->mAutoCalResult.mnCalBemf,
-                                               pDRV2625->mAutoCalResult.mnCalGain);
-                               }       
-                       }else if(mode == MODE_DIAGNOSTIC){
-                               pDRV2625->mDiagResult.mnResult = status;
-                               if((status&DIAG_MASK) != DIAG_SUCCESS){
-                                       dev_err(pDRV2625->dev, "Diagnostic fail\n");
-                               }else{
-                                       pDRV2625->mDiagResult.mnDiagZ = 
-                                               drv2625_reg_read(pDRV2625, DRV2625_REG_DIAG_Z);
-                                       pDRV2625->mDiagResult.mnDiagK = 
-                                               drv2625_reg_read(pDRV2625, DRV2625_REG_DIAG_K);
-                                       dev_dbg(pDRV2625->dev, 
-                                               "Diag : ZResult=0x%x, CurrentK=0x%x\n",
-                                               pDRV2625->mDiagResult.mnDiagZ,
-                                               pDRV2625->mDiagResult.mnDiagK);
-                               }                                               
-                       }else if(mode == MODE_WAVEFORM_SEQUENCER){
-                               dev_dbg(pDRV2625->dev, 
+               if (status & PRG_ERR_MASK)
+                       dev_err(pDRV2625->dev, "ERROR, PRG error!!\n");
+
+               if (status & PROCESS_DONE_MASK) {
+                       nResult = drv2625_reg_read(pDRV2625, DRV2625_REG_MODE);
+                       if (nResult < 0)
+                               goto err;
+
+                       mode =  nResult & WORKMODE_MASK;
+                       if (mode == MODE_CALIBRATION)
+                               nResult = drv2625_get_calibration_result(pDRV2625, status);
+                       else if (mode == MODE_DIAGNOSTIC)
+                               nResult = drv2625_get_diag_result(pDRV2625, status);
+                       else if (mode == MODE_WAVEFORM_SEQUENCER)
+                               dev_dbg(pDRV2625->dev,
                                        "Waveform Sequencer Playback finished\n");
-                       }else if(mode == MODE_RTP){
-                               dev_dbg(pDRV2625->dev, 
-                                       "RTP IRQ\n");
-                       }
+                       else if(mode == MODE_RTP)
+                               dev_dbg(pDRV2625->dev, "RTP IRQ\n");
                }
-               
-               if((mode != MODE_RTP)&&
-                       (pDRV2625->mnVibratorPlaying == YES)){
-                       dev_info(pDRV2625->dev, "release wklock\n");
-                       pDRV2625->mnVibratorPlaying = NO;
-                       wake_unlock(&pDRV2625->wklock);
-               }
-                       
+
+               if ((mode != MODE_RTP) && (pDRV2625->mnVibratorPlaying == YES))
+                       drv2625_set_stopflag(pDRV2625);
+
                pDRV2625->mnWorkMode &= ~WORK_IRQ;
        }
-       
-       if(pDRV2625->mnWorkMode & WORK_VIBRATOR){
+
+       if (pDRV2625->mnWorkMode & WORK_VIBRATOR) {
                drv2625_stop(pDRV2625);
                pDRV2625->mnWorkMode &= ~WORK_VIBRATOR;
        }
-       
+
+       if (pDRV2625->mnWorkMode & WORK_EFFECTSEQUENCER) {
+               status = drv2625_reg_read(pDRV2625, DRV2625_REG_GO);
+               if ((status < 0) || (status == STOP) || !pDRV2625->mnVibratorPlaying) {
+                       drv2625_stop(pDRV2625);
+                       pDRV2625->mnWorkMode &= ~WORK_EFFECTSEQUENCER;
+               } else {
+                       if (!hrtimer_active(&pDRV2625->timer)) {
+                               if (g_logEnable)
+                                       dev_dbg(pDRV2625->dev, "will check GO bit after %d ms\n", POLL_GO_BIT_INTERVAL);
+                               hrtimer_start(&pDRV2625->timer, 
+                                       ns_to_ktime((u64)POLL_GO_BIT_INTERVAL * NSEC_PER_MSEC), HRTIMER_MODE_REL);
+                       }
+               }
+       }
+
+       if (pDRV2625->mnWorkMode & WORK_CALIBRATION) {
+               status = drv2625_reg_read(pDRV2625, DRV2625_REG_GO);
+               if ((status < 0) || (status == STOP) || !pDRV2625->mnVibratorPlaying) {
+                       drv2625_stop(pDRV2625);
+                       pDRV2625->mnWorkMode &= ~WORK_CALIBRATION;
+                       if (status < 0)
+                               goto err;
+                       nResult = drv2625_reg_read(pDRV2625, DRV2625_REG_STATUS);
+                       if (nResult >= 0)
+                               nResult = drv2625_get_calibration_result(pDRV2625, nResult);
+               } else {
+                       if (!hrtimer_active(&pDRV2625->timer)) {
+                               if (g_logEnable)
+                                       dev_dbg(pDRV2625->dev, "will check GO bit after %d ms\n", POLL_GO_BIT_INTERVAL);
+                               hrtimer_start(&pDRV2625->timer, 
+                                       ns_to_ktime((u64)POLL_GO_BIT_INTERVAL * NSEC_PER_MSEC), HRTIMER_MODE_REL);
+                       }
+               }
+       }
+
+       if (pDRV2625->mnWorkMode & WORK_DIAGNOSTIC) {
+               status = drv2625_reg_read(pDRV2625, DRV2625_REG_GO);
+               if ((status < 0) || (status == STOP) || !pDRV2625->mnVibratorPlaying) {
+                       drv2625_stop(pDRV2625);
+                       pDRV2625->mnWorkMode &= ~WORK_DIAGNOSTIC;
+                       if (status < 0)
+                               goto err;
+                       nResult = drv2625_reg_read(pDRV2625, DRV2625_REG_STATUS);
+                       if (nResult >= 0)
+                               nResult = drv2625_get_diag_result(pDRV2625, nResult);
+               } else {
+                       if (!hrtimer_active(&pDRV2625->timer)) {
+                               if (g_logEnable)
+                                       dev_dbg(pDRV2625->dev, "will check GO bit after %d ms\n", POLL_GO_BIT_INTERVAL);
+                               hrtimer_start(&pDRV2625->timer, 
+                                       ns_to_ktime((u64)POLL_GO_BIT_INTERVAL * NSEC_PER_MSEC), HRTIMER_MODE_REL);
+                       }
+               }
+       }
+
+err:
+
        mutex_unlock(&pDRV2625->lock);
 }
 
 static int dev_auto_calibrate(struct drv2625_data *pDRV2625)
 {
-       int ret = 0;
-       
-       dev_info(pDRV2625->dev, "%s\n", __FUNCTION__);
+       int nResult = 0;
+
+       dev_info(pDRV2625->dev, "%s\n", __func__);
        wake_lock(&pDRV2625->wklock);
-       pDRV2625->mnVibratorPlaying = YES;      
-       drv2625_change_mode(pDRV2625, MODE_CALIBRATION);
-       ret = drv2625_set_go_bit(pDRV2625, GO);
-       if(ret < 0){
-               dev_warn(pDRV2625->dev, "calibration start fail\n");
+       if (g_logEnable)
+               dev_dbg(pDRV2625->dev, "wklock lock");
+
+       nResult = drv2625_change_mode(pDRV2625, MODE_CALIBRATION);
+       if (nResult < 0)
+               goto end;
+
+       nResult = drv2625_set_go_bit(pDRV2625, GO);
+       if (nResult < 0)
+               goto end;
+
+       dev_dbg(pDRV2625->dev, "calibration start\n");
+       pDRV2625->mnVibratorPlaying = YES;
+
+       if (!pDRV2625->mbIRQUsed) {
+               pDRV2625->mnWorkMode |= WORK_CALIBRATION;
+               schedule_work(&pDRV2625->vibrator_work);
+       }
+
+end:
+       if (nResult < 0) {
                wake_unlock(&pDRV2625->wklock);
-               pDRV2625->mnVibratorPlaying = NO;                       
-       }else{
-               dev_dbg(pDRV2625->dev, "calibration start\n");
+               if (g_logEnable)
+                       dev_dbg(pDRV2625->dev, "wklock unlock");
        }
-       return ret;
+       return nResult;
 }
 
 static int dev_run_diagnostics(struct drv2625_data *pDRV2625)
 {
-       int ret = 0;
-       
-       dev_info(pDRV2625->dev, "%s\n", __FUNCTION__);
+       int nResult = 0;
+
+       dev_info(pDRV2625->dev, "%s\n", __func__);
        wake_lock(&pDRV2625->wklock);
-       pDRV2625->mnVibratorPlaying = YES;      
-       drv2625_change_mode(pDRV2625, MODE_DIAGNOSTIC);
-       ret = drv2625_set_go_bit(pDRV2625, GO);
-       if(ret < 0){
-               dev_warn(pDRV2625->dev, "Diag start fail\n");
+       if (g_logEnable)
+               dev_dbg(pDRV2625->dev, "wklock lock");
+
+       nResult = drv2625_change_mode(pDRV2625, MODE_DIAGNOSTIC);
+       if (nResult < 0) 
+               goto end;
+
+       nResult = drv2625_set_go_bit(pDRV2625, GO);
+       if (nResult < 0)
+               goto end;
+
+       dev_dbg(pDRV2625->dev, "Diag start\n");
+       pDRV2625->mnVibratorPlaying = YES;
+
+       if (!pDRV2625->mbIRQUsed) {
+               pDRV2625->mnWorkMode |= WORK_DIAGNOSTIC;
+               schedule_work(&pDRV2625->vibrator_work);
+       }
+
+end:
+       if (nResult < 0) {
                wake_unlock(&pDRV2625->wklock);
-               pDRV2625->mnVibratorPlaying = NO;                       
-       }else{
-               dev_dbg(pDRV2625->dev, "Diag start\n");
+               if (g_logEnable)
+                       dev_dbg(pDRV2625->dev, "wklock unlock");
        }
-       
-       return ret;
+       return nResult;
 }
 
 static int drv2625_playEffect(struct drv2625_data *pDRV2625)
 {
-       int ret = 0;
-       dev_info(pDRV2625->dev, "%s\n", __FUNCTION__);
+       int nResult = 0;
+
+       dev_info(pDRV2625->dev, "%s\n", __func__);
        wake_lock(&pDRV2625->wklock);
-       pDRV2625->mnVibratorPlaying = YES;      
-       drv2625_change_mode(pDRV2625, MODE_WAVEFORM_SEQUENCER);
-       ret = drv2625_set_go_bit(pDRV2625, GO);
-       if(ret < 0){
-               dev_warn(pDRV2625->dev, "effects start fail\n");
+       if (g_logEnable)
+               dev_dbg(pDRV2625->dev, "wklock lock");
+
+       nResult = drv2625_change_mode(pDRV2625, MODE_WAVEFORM_SEQUENCER);
+       if (nResult < 0) 
+               goto end;
+
+       nResult = drv2625_set_go_bit(pDRV2625, GO);
+       if (nResult < 0) 
+               goto end;
+
+       dev_dbg(pDRV2625->dev, "effects start\n");
+       pDRV2625->mnVibratorPlaying = YES;
+
+       if (!pDRV2625->mbIRQUsed) {
+               pDRV2625->mnWorkMode |= WORK_EFFECTSEQUENCER;
+               schedule_work(&pDRV2625->vibrator_work);
+       }
+
+end:
+       if (nResult < 0) {
                wake_unlock(&pDRV2625->wklock);
-               pDRV2625->mnVibratorPlaying = NO;                       
-       }else{
-               dev_dbg(pDRV2625->dev, "effects start\n");
+               dev_dbg(pDRV2625->dev, "wklock unlock");
        }
-       
-       return ret;
+       return nResult;
 }
        
 static int drv2625_config_waveform(struct drv2625_data *pDRV2625,
        struct drv2625_wave_setting *psetting)
 {
-       int ret = 0;
+       int nResult = 0;
        int value = 0;
-       
-       ret = drv2625_reg_write(pDRV2625, 
-                       DRV2625_REG_MAIN_LOOP, psetting->mnLoop&0x07);
-       if(ret >= 0){
-               value |= ((psetting->mnInterval&0x01)<<INTERVAL_SHIFT);
-               value |= (psetting->mnScale&0x03);
-               drv2625_set_bits(pDRV2625,
-                       DRV2625_REG_CONTROL2, INTERVAL_MASK|SCALE_MASK, value);
+
+       nResult = drv2625_reg_write(pDRV2625,
+                       DRV2625_REG_MAIN_LOOP, psetting->mnLoop & 0x07);
+       if (nResult >= 0) {
+               value |= ((psetting->mnInterval & 0x01) << INTERVAL_SHIFT);
+               value |= (psetting->mnScale & 0x03);
+               nResult = drv2625_set_bits(pDRV2625, DRV2625_REG_CONTROL2,
+                                       INTERVAL_MASK | SCALE_MASK, value);
        }
-       return ret;
+       return nResult;
 }
 
 static int drv2625_set_waveform(struct drv2625_data *pDRV2625,
        struct drv2625_waveform_sequencer *pSequencer)
 {
-       int ret = 0;
+       int nResult = 0;
        int i = 0;
        unsigned char loop[2] = {0};
        unsigned char effects[DRV2625_SEQUENCER_SIZE] = {0};
        unsigned char len = 0;
-       
-       for(i = 0; i < DRV2625_SEQUENCER_SIZE; i++){
+
+       for (i = 0; i < DRV2625_SEQUENCER_SIZE; i++) {
                len++;
-               if(pSequencer->msWaveform[i].mnEffect != 0){                    
-                       if(i < 4) 
-                               loop[0] |= 
-                                               (pSequencer->msWaveform[i].mnLoop << (2*i));
+               if (pSequencer->msWaveform[i].mnEffect != 0) {
+                       if (i < 4) 
+                               loop[0] |= (pSequencer->msWaveform[i].mnLoop << (2*i));
                        else
-                               loop[1] |= 
-                                               (pSequencer->msWaveform[i].mnLoop << (2*(i-4)));
-                       
+                               loop[1] |= (pSequencer->msWaveform[i].mnLoop << (2*(i-4)));
+
                        effects[i] = pSequencer->msWaveform[i].mnEffect;
-               }else{                  
+               } else
                        break;
-               }               
        }
-       
-       if(len == 1)
-               ret = drv2625_reg_write(pDRV2625, DRV2625_REG_SEQUENCER_1, 0);
+
+       if (len == 1)
+               nResult = drv2625_reg_write(pDRV2625, DRV2625_REG_SEQUENCER_1, 0);
        else 
-               ret = drv2625_bulk_write(pDRV2625, DRV2625_REG_SEQUENCER_1, effects, len);
+               nResult = drv2625_bulk_write(pDRV2625, DRV2625_REG_SEQUENCER_1, effects, len);
 
-       if(ret < 0)
+       if (nResult < 0) 
                dev_err(pDRV2625->dev, "sequence error\n");
+               goto end;
        }
-       
-       if(ret >= 0){
-               if(len > 1){
-                       if((len-1) <= 4)
-                               drv2625_reg_write(pDRV2625, DRV2625_REG_SEQ_LOOP_1, loop[0]);
-                       else
-                               drv2625_bulk_write(pDRV2625, DRV2625_REG_SEQ_LOOP_1, loop, 2);  
-               }
+
+       if (len > 1) {
+               if ((len-1) <= 4)
+                       drv2625_reg_write(pDRV2625, DRV2625_REG_SEQ_LOOP_1, loop[0]);
+               else
+                       drv2625_bulk_write(pDRV2625, DRV2625_REG_SEQ_LOOP_1, loop, 2);
        }
-       
-       return ret;
+
+end:
+
+       return nResult;
 }
 
 static int drv2625_file_open(struct inode *inode, struct file *file)
 {
-       if (!try_module_get(THIS_MODULE)) return -ENODEV;
+       if (!try_module_get(THIS_MODULE))
+               return -ENODEV;
 
        file->private_data = (void*)g_DRV2625data;
        return 0;
@@ -520,296 +701,280 @@ static long drv2625_file_unlocked_ioctl(struct file *file, unsigned int cmd, uns
 {
        struct drv2625_data *pDRV2625 = file->private_data;
        //void __user *user_arg = (void __user *)arg;
-       int ret = 0;
-       
+       int nResult = 0;
+
        mutex_lock(&pDRV2625->lock);
-       
+
        dev_dbg(pDRV2625->dev, "ioctl 0x%x\n", cmd);
-       
+
        switch (cmd) {
-               
+
        }
-       
+
        mutex_unlock(&pDRV2625->lock);
-       
-       return ret;
+
+       return nResult;
 }
 
 static ssize_t drv2625_file_read(struct file* filp, char* buff, size_t length, loff_t* offset)
 {
        struct drv2625_data *pDRV2625 = (struct drv2625_data *)filp->private_data;
-       int ret = 0;
+       int nResult = 0;
        unsigned char value = 0;
        unsigned char *p_kBuf = NULL;
 
        mutex_lock(&pDRV2625->lock);
 
-       switch(pDRV2625->mnFileCmd)
-       {
-               case HAPTIC_CMDID_REG_READ:
-               {
-                       if(length == 1){
-                               ret = drv2625_reg_read(pDRV2625, pDRV2625->mnCurrentReg);
-                               if( 0 > ret) {
-                                       dev_err(pDRV2625->dev, "dev read fail %d\n", ret);
-                               }else{
-                                       value = ret;
-                                       ret = copy_to_user(buff, &value, 1);
-                                       if (0 != ret) {
-                                               /* Failed to copy all the data, exit */
-                                               dev_err(pDRV2625->dev, "copy to user fail %d\n", ret);
-                                       }       
+       switch (pDRV2625->mnFileCmd) {
+       case HAPTIC_CMDID_REG_READ:
+               if (length == 1) {
+                       nResult = drv2625_reg_read(pDRV2625, pDRV2625->mnCurrentReg);
+                       if (nResult >= 0) {
+                               value = nResult;
+                               nResult = copy_to_user(buff, &value, 1);
+                               if (0 != nResult) {
+                                       /* Failed to copy all the data, exit */
+                                       dev_err(pDRV2625->dev, "copy to user fail %d\n", nResult);
                                }
-                       }else if(length > 1){
-                               p_kBuf = (unsigned char *)kzalloc(length, GFP_KERNEL);
-                               if(p_kBuf != NULL){
-                                       ret = drv2625_bulk_read(pDRV2625, 
-                                               pDRV2625->mnCurrentReg, p_kBuf, length);
-                                       if( 0 > ret) {
-                                               dev_err(pDRV2625->dev, "dev bulk read fail %d\n", ret);
-                                       }else{
-                                               ret = copy_to_user(buff, p_kBuf, length);
-                                               if (0 != ret) {
-                                                       /* Failed to copy all the data, exit */
-                                                       dev_err(pDRV2625->dev, "copy to user fail %d\n", ret);
-                                               }
+                       }
+               } else if (length > 1) {
+                       p_kBuf = (unsigned char *)kzalloc(length, GFP_KERNEL);
+                       if (p_kBuf != NULL) {
+                               nResult = drv2625_bulk_read(pDRV2625,
+                                       pDRV2625->mnCurrentReg, p_kBuf, length);
+                               if (nResult >= 0) {
+                                       nResult = copy_to_user(buff, p_kBuf, length);
+                                       if (0 != nResult) {
+                                               /* Failed to copy all the data, exit */
+                                               dev_err(pDRV2625->dev, "copy to user fail %d\n", nResult);
                                        }
-                                       
-                                       kfree(p_kBuf);
-                               }else{
-                                       dev_err(pDRV2625->dev, "read no mem\n");
-                                       ret = -ENOMEM;
                                }
+
+                               kfree(p_kBuf);
+                       } else {
+                               dev_err(pDRV2625->dev, "read no mem\n");
+                               nResult = -ENOMEM;
                        }
-                       break;
                }
-               
-               case HAPTIC_CMDID_RUN_DIAG:
-               {
-                       if(pDRV2625->mnVibratorPlaying){
-                               length = 0;
-                       }else{
-                               unsigned char buf[3] ;
-                               buf[0] = pDRV2625->mDiagResult.mnResult;
-                               buf[1] = pDRV2625->mDiagResult.mnDiagZ;
-                               buf[2] = pDRV2625->mDiagResult.mnDiagK;
-                               ret = copy_to_user(buff, buf, 3);
-                               if (0 != ret) {
-                                       /* Failed to copy all the data, exit */
-                                       dev_err(pDRV2625->dev, "copy to user fail %d\n", ret);
-                               }
+               break;
+
+       case HAPTIC_CMDID_RUN_DIAG:
+               if (pDRV2625->mnVibratorPlaying)
+                       length = 0;
+               else {
+                       unsigned char buf[3];
+
+                       buf[0] = pDRV2625->mDiagResult.mnResult;
+                       buf[1] = pDRV2625->mDiagResult.mnDiagZ;
+                       buf[2] = pDRV2625->mDiagResult.mnDiagK;
+                       nResult = copy_to_user(buff, buf, 3);
+                       if (0 != nResult) {
+                               /* Failed to copy all the data, exit */
+                               dev_err(pDRV2625->dev, "copy to user fail %d\n", nResult);
                        }
-                       break;
                }
-               
-               case HAPTIC_CMDID_RUN_CALIBRATION:
-               {
-                       if(pDRV2625->mnVibratorPlaying){
-                               length = 0;
-                       }else{
-                               unsigned char buf[4] ;
-                               buf[0] = pDRV2625->mAutoCalResult.mnResult;
-                               buf[1] = pDRV2625->mAutoCalResult.mnCalComp;
-                               buf[2] = pDRV2625->mAutoCalResult.mnCalBemf;
-                               buf[3] = pDRV2625->mAutoCalResult.mnCalGain;
-                               ret = copy_to_user(buff, buf, 4);
-                               if (0 != ret) {
-                                       /* Failed to copy all the data, exit */
-                                       dev_err(pDRV2625->dev, "copy to user fail %d\n", ret);
-                               }
+               break;
+
+       case HAPTIC_CMDID_RUN_CALIBRATION:
+               if (pDRV2625->mnVibratorPlaying)
+                       length = 0;
+               else {
+                       unsigned char buf[4];
+
+                       buf[0] = pDRV2625->mAutoCalResult.mnResult;
+                       buf[1] = pDRV2625->mAutoCalResult.mnCalComp;
+                       buf[2] = pDRV2625->mAutoCalResult.mnCalBemf;
+                       buf[3] = pDRV2625->mAutoCalResult.mnCalGain;
+                       nResult = copy_to_user(buff, buf, 4);
+                       if (0 != nResult) {
+                               /* Failed to copy all the data, exit */
+                               dev_err(pDRV2625->dev, "copy to user fail %d\n", nResult);
                        }
-                       break;
                }
-               
-               case HAPTIC_CMDID_CONFIG_WAVEFORM:
-               {
-                       if(length == sizeof(struct drv2625_wave_setting)){
-                               struct drv2625_wave_setting wavesetting;                
-                               value = drv2625_reg_read(pDRV2625, DRV2625_REG_CONTROL2);
-                               wavesetting.mnLoop = 
-                                       drv2625_reg_read(pDRV2625, DRV2625_REG_MAIN_LOOP)&0x07;
-                               wavesetting.mnInterval = ((value&INTERVAL_MASK)>>INTERVAL_SHIFT);
-                               wavesetting.mnScale = (value&SCALE_MASK);
-                               ret = copy_to_user(buff, &wavesetting, length);
-                               if (0 != ret) {
-                                       /* Failed to copy all the data, exit */
-                                       dev_err(pDRV2625->dev, "copy to user fail %d\n", ret);
-                               }       
+               break;
+
+       case HAPTIC_CMDID_CONFIG_WAVEFORM:
+               if (length == sizeof(struct drv2625_wave_setting)) {
+                       struct drv2625_wave_setting wavesetting;
+
+                       value = drv2625_reg_read(pDRV2625, DRV2625_REG_CONTROL2);
+                       wavesetting.mnLoop = drv2625_reg_read(pDRV2625, DRV2625_REG_MAIN_LOOP)&0x07;
+                       wavesetting.mnInterval = ((value&INTERVAL_MASK)>>INTERVAL_SHIFT);
+                       wavesetting.mnScale = (value&SCALE_MASK);
+                       nResult = copy_to_user(buff, &wavesetting, length);
+                       if (0 != nResult) {
+                               /* Failed to copy all the data, exit */
+                               dev_err(pDRV2625->dev, "copy to user fail %d\n", nResult);
                        }
-                       
-                       break;
                }
-               
-               case HAPTIC_CMDID_SET_SEQUENCER:
-               {
-                       if(length == sizeof(struct drv2625_waveform_sequencer)){
-                               struct drv2625_waveform_sequencer sequencer;
-                               unsigned char effects[DRV2625_SEQUENCER_SIZE] = {0};
-                               unsigned char loop[2] = {0};
-                               int i = 0;
-                               ret = drv2625_bulk_read(pDRV2625, 
-                                               DRV2625_REG_SEQUENCER_1, 
+               break;
+
+       case HAPTIC_CMDID_SET_SEQUENCER:
+               if (length == sizeof(struct drv2625_waveform_sequencer)) {
+                       struct drv2625_waveform_sequencer sequencer;
+                       unsigned char effects[DRV2625_SEQUENCER_SIZE] = {0};
+                       unsigned char loop[2] = {0};
+                       int i = 0;
+
+                       nResult = drv2625_bulk_read(pDRV2625, DRV2625_REG_SEQUENCER_1,
                                                effects, DRV2625_SEQUENCER_SIZE);
-                               if(ret < 0){
-                                       dev_err(pDRV2625->dev, "bulk read error %d\n", ret);
-                                       break;
-                               }
-                                       
-                               ret = drv2625_bulk_read(pDRV2625, 
-                                               DRV2625_REG_SEQ_LOOP_1,
-                                               loop, 2);
-                                               
-                               for(i=0; i < DRV2625_SEQUENCER_SIZE; i++){
-                                       sequencer.msWaveform[i].mnEffect = effects[i];
-                                       if(i < 4)
-                                               sequencer.msWaveform[i].mnLoop = ((loop[0]>>(2*i))&0x03);
-                                       else
-                                               sequencer.msWaveform[i].mnLoop = ((loop[1]>>(2*(i-4)))&0x03);
-                               }
-                               
-                               ret = copy_to_user(buff, &sequencer, length);
-                               if (0 != ret) {
-                                       /* Failed to copy all the data, exit */
-                                       dev_err(pDRV2625->dev, "copy to user fail %d\n", ret);
-                               }       
+                       if (nResult < 0)
+                               break;
+
+                       nResult = drv2625_bulk_read(pDRV2625, DRV2625_REG_SEQ_LOOP_1, loop, 2);
+                       if (nResult < 0)
+                               break;
+
+                       for (i = 0; i < DRV2625_SEQUENCER_SIZE; i++) {
+                               sequencer.msWaveform[i].mnEffect = effects[i];
+                               if (i < 4)
+                                       sequencer.msWaveform[i].mnLoop = ((loop[0]>>(2*i))&0x03);
+                               else
+                                       sequencer.msWaveform[i].mnLoop = ((loop[1]>>(2*(i-4)))&0x03);
+                       }
+
+                       nResult = copy_to_user(buff, &sequencer, length);
+                       if (0 != nResult) {
+                               /* Failed to copy all the data, exit */
+                               dev_err(pDRV2625->dev, "copy to user fail %d\n", nResult);
                        }
-                       
-                       break;
                }
+               break;
                
-               default:
-                       pDRV2625->mnFileCmd = 0;
-                       break;
+       case HAPTIC_CMDID_REGLOG_ENABLE:
+               if (length == 1) {
+                       nResult = copy_to_user(buff, &g_logEnable, 1);
+                       if (0 != nResult) {
+                               /* Failed to copy all the data, exit */
+                               dev_err(pDRV2625->dev, "copy to user fail %d\n", nResult);
+                       }
+               }
+               break;
+
+       default:
+               pDRV2625->mnFileCmd = 0;
+               break;
        }
-       
+
        mutex_unlock(&pDRV2625->lock);
-       
+
     return length;
 }
 
 static ssize_t drv2625_file_write(struct file* filp, const char* buff, size_t len, loff_t* off)
 {
-       struct drv2625_data *pDRV2625 = 
-               (struct drv2625_data *)filp->private_data;
+       struct drv2625_data *pDRV2625 = (struct drv2625_data *)filp->private_data;
        unsigned char *p_kBuf = NULL;
-       int ret = 0;
-       
-    mutex_lock(&pDRV2625->lock);
-       
+       int nResult = 0;
+
+       mutex_lock(&pDRV2625->lock);
+
        p_kBuf = (unsigned char *)kzalloc(len, GFP_KERNEL);
-       if(p_kBuf == NULL) {
+       if (p_kBuf == NULL) {
                dev_err(pDRV2625->dev, "write no mem\n");
                goto err;
        }
-       
-       ret = copy_from_user(p_kBuf, buff, len);
-       if (0 != ret) {
+
+       nResult = copy_from_user(p_kBuf, buff, len);
+       if (0 != nResult) {
                dev_err(pDRV2625->dev,"copy_from_user failed.\n");
                goto err;
        }
 
        pDRV2625->mnFileCmd = p_kBuf[0];
-       
-    switch(pDRV2625->mnFileCmd)
-    {
-               case HAPTIC_CMDID_REG_READ:
-               {
-                       if(len == 2){
-                               pDRV2625->mnCurrentReg = p_kBuf[1];
-                       }else{
-                               dev_err(pDRV2625->dev, 
-                                       " read cmd len %d err\n", len);
-                       }
-                       break;
-               }
-               
-               case HAPTIC_CMDID_REG_WRITE:
-               {
-                       if((len-1) == 2){
-                               drv2625_reg_write(pDRV2625, p_kBuf[1], p_kBuf[2]);      
-                       }else if((len-1)>2){
-                               drv2625_bulk_write(pDRV2625, p_kBuf[1], &p_kBuf[2], len-2);
-                       }else{
-                               dev_err(pDRV2625->dev, 
-                                       "%s, reg_write len %d error\n", __FUNCTION__, len);
-                       }
-                       break;
-               }
-               
-               case HAPTIC_CMDID_REG_SETBIT:
-               {
-                       if(len == 4){
-                               drv2625_set_bits(pDRV2625, p_kBuf[1], p_kBuf[2], p_kBuf[3]);
-                       }else{
-                               dev_err(pDRV2625->dev, 
-                                       "setbit len %d error\n", len);
-                       }
-                       break;
-               }       
-               
-               case HAPTIC_CMDID_RUN_DIAG:
-               {
-                       drv2625_stop(pDRV2625); 
-                       drv2625_enableIRQ(pDRV2625, NO);        
-                       ret = dev_run_diagnostics(pDRV2625);
-                       if(ret < 0) drv2625_disableIRQ(pDRV2625);
-                       break;
-               }
-               
-               case HAPTIC_CMDID_RUN_CALIBRATION:
-               {
-                       drv2625_stop(pDRV2625); 
-                       drv2625_enableIRQ(pDRV2625, NO);        
-                       ret = dev_auto_calibrate(pDRV2625);
-                       if(ret < 0) drv2625_disableIRQ(pDRV2625);
+
+       switch(pDRV2625->mnFileCmd) {
+       case HAPTIC_CMDID_REG_READ:
+               if (len == 2)
+                       pDRV2625->mnCurrentReg = p_kBuf[1];
+               else
+                       dev_err(pDRV2625->dev, " read cmd len %d err\n", len);
+               break;
+
+       case HAPTIC_CMDID_REG_WRITE:
+               if ((len - 1) == 2)
+                       nResult = drv2625_reg_write(pDRV2625, p_kBuf[1], p_kBuf[2]);
+               else if ((len - 1) > 2)
+                       nResult = drv2625_bulk_write(pDRV2625, p_kBuf[1], &p_kBuf[2], len-2);
+               else
+                       dev_err(pDRV2625->dev, "%s, reg_write len %d error\n", __func__, len);
+               break;
+
+       case HAPTIC_CMDID_REG_SETBIT:
+               if (len == 4)
+                       nResult = drv2625_set_bits(pDRV2625, p_kBuf[1], p_kBuf[2], p_kBuf[3]);
+               else
+                       dev_err(pDRV2625->dev, "setbit len %d error\n", len);
+               break;
+
+       case HAPTIC_CMDID_RUN_DIAG:
+               nResult = drv2625_stop(pDRV2625);
+               if (nResult < 0)
                        break;
-               }
-               
-               case HAPTIC_CMDID_CONFIG_WAVEFORM:
-               {
-                       if(len == (1+ sizeof(struct drv2625_wave_setting))){
-                               struct drv2625_wave_setting wavesetting;
-                               memcpy(&wavesetting, &p_kBuf[1], 
-                                       sizeof(struct drv2625_wave_setting));
-                               ret = drv2625_config_waveform(pDRV2625, &wavesetting);
-                       }else{
-                               dev_dbg(pDRV2625->dev, "pass cmd, prepare for read\n");
-                       }
-               }
-               break;  
-
-               case HAPTIC_CMDID_SET_SEQUENCER:
-               {
-                       if(len == (1+ sizeof(struct drv2625_waveform_sequencer))){
-                               struct drv2625_waveform_sequencer sequencer;
-                               memcpy(&sequencer, &p_kBuf[1], 
-                                       sizeof(struct drv2625_waveform_sequencer));
-                               ret = drv2625_set_waveform(pDRV2625, &sequencer);
-                       }else{
-                               dev_dbg(pDRV2625->dev, "pass cmd, prepare for read\n");
-                       }
-               }
-               break;  
-               
-               case HAPTIC_CMDID_PLAY_EFFECT_SEQUENCE:
-               {
-                       drv2625_stop(pDRV2625); 
-                       drv2625_enableIRQ(pDRV2625, NO);        
-                       ret = drv2625_playEffect(pDRV2625);
-                       if(ret < 0) drv2625_disableIRQ(pDRV2625);
+               nResult = dev_run_diagnostics(pDRV2625);
+               if ((nResult >= 0) && pDRV2625->mbIRQUsed)
+                       drv2625_enableIRQ(pDRV2625, NO);
+               break;
+
+
+       case HAPTIC_CMDID_RUN_CALIBRATION:
+               nResult = drv2625_stop(pDRV2625);
+               if (nResult < 0)
                        break;
-               }
-                               
-               default:
-                       dev_err(pDRV2625->dev, 
-                       "%s, unknown cmd\n", __FUNCTION__);
+
+               nResult = dev_auto_calibrate(pDRV2625);
+               if ((nResult >= 0) && pDRV2625->mbIRQUsed)
+                       drv2625_enableIRQ(pDRV2625, NO);
+               break;
+
+       case HAPTIC_CMDID_CONFIG_WAVEFORM:
+               if (len == (1 + sizeof(struct drv2625_wave_setting))) {
+                       struct drv2625_wave_setting wavesetting;
+
+                       memcpy(&wavesetting, &p_kBuf[1], sizeof(struct drv2625_wave_setting));
+                       nResult = drv2625_config_waveform(pDRV2625, &wavesetting);
+               } else
+                       dev_dbg(pDRV2625->dev, "pass cmd, prepare for read\n");
+               break;
+
+       case HAPTIC_CMDID_SET_SEQUENCER:
+               if (len == (1 + sizeof(struct drv2625_waveform_sequencer))) {
+                       struct drv2625_waveform_sequencer sequencer;
+
+                       memcpy(&sequencer, &p_kBuf[1], sizeof(struct drv2625_waveform_sequencer));
+                       nResult = drv2625_set_waveform(pDRV2625, &sequencer);
+               } else
+                       dev_dbg(pDRV2625->dev, "pass cmd, prepare for read\n");
+               break;
+
+       case HAPTIC_CMDID_PLAY_EFFECT_SEQUENCE:
+               nResult = drv2625_stop(pDRV2625);
+               if (nResult < 0)
                        break;
-    }
-       
+
+               nResult = drv2625_playEffect(pDRV2625);
+               if ((nResult >= 0) && pDRV2625->mbIRQUsed)
+                       drv2625_enableIRQ(pDRV2625, NO);
+               break;
+
+       case HAPTIC_CMDID_STOP:
+               nResult = drv2625_stop(pDRV2625);
+               break;
+
+       case HAPTIC_CMDID_REGLOG_ENABLE:
+               if (len == 2)
+                       g_logEnable = p_kBuf[1];
+               break;
+
+       default:
+               dev_err(pDRV2625->dev, "%s, unknown cmd\n", __func__);
+               break;
+       }
+
 err:
-       if(p_kBuf != NULL)
+       if (p_kBuf != NULL)
                kfree(p_kBuf);
-       
+
     mutex_unlock(&pDRV2625->lock);
 
     return len;
@@ -834,34 +999,32 @@ static struct miscdevice drv2625_misc =
  
 static int Haptics_init(struct drv2625_data *pDRV2625)
 {
-    int ret = 0;
-       
+       int nResult = 0;
+
        pDRV2625->to_dev.name = "vibrator";
        pDRV2625->to_dev.get_time = vibrator_get_time;
        pDRV2625->to_dev.enable = vibrator_enable;
 
-       ret = timed_output_dev_register(&(pDRV2625->to_dev));
-    if ( ret < 0){
-        dev_err(pDRV2625->dev, 
-                       "drv2625: fail to create timed output dev\n");
-        return ret;
-    }
-       
-       ret = misc_register(&drv2625_misc);
-       if (ret) {
-               dev_err(pDRV2625->dev, 
-                       "drv2625 misc fail: %d\n", ret);
-               return ret;
+       nResult = timed_output_dev_register(&(pDRV2625->to_dev));
+       if (nResult < 0) {
+               dev_err(pDRV2625->dev, "drv2625: fail to create timed output dev\n");
+               return nResult;
        }
-       
-    hrtimer_init(&pDRV2625->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
-    pDRV2625->timer.function = vibrator_timer_func;
-    INIT_WORK(&pDRV2625->vibrator_work, vibrator_work_routine);
-    
-    wake_lock_init(&pDRV2625->wklock, WAKE_LOCK_SUSPEND, "vibrator");
-    mutex_init(&pDRV2625->lock);
-       
-    return 0;
+
+       nResult = misc_register(&drv2625_misc);
+       if (nResult) {
+               dev_err(pDRV2625->dev, "drv2625 misc fail: %d\n", nResult);
+               return nResult;
+       }
+
+       hrtimer_init(&pDRV2625->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       pDRV2625->timer.function = vibrator_timer_func;
+       INIT_WORK(&pDRV2625->vibrator_work, vibrator_work_routine);
+
+       wake_lock_init(&pDRV2625->wklock, WAKE_LOCK_SUSPEND, "vibrator");
+       mutex_init(&pDRV2625->lock);
+
+       return 0;
 }
 
 static void dev_init_platform_data(struct drv2625_data *pDRV2625)
@@ -870,345 +1033,315 @@ static void dev_init_platform_data(struct drv2625_data *pDRV2625)
        struct actuator_data actuator = pDrv2625Platdata->msActuator;
        unsigned char value_temp = 0;
        unsigned char mask_temp = 0;
-       
+
        drv2625_set_bits(pDRV2625, 
                DRV2625_REG_MODE, PINFUNC_MASK, (PINFUNC_INT<<PINFUNC_SHIFT));
-       
-       if((actuator.mnActuatorType == ERM)||
-               (actuator.mnActuatorType == LRA)){
+
+       if ((actuator.mnActuatorType == ERM)
+               || (actuator.mnActuatorType == LRA)) {
                mask_temp |= ACTUATOR_MASK;
                value_temp |= (actuator.mnActuatorType << ACTUATOR_SHIFT);
        }
-       
-       if((pDrv2625Platdata->mnLoop == CLOSE_LOOP)||
-               (pDrv2625Platdata->mnLoop == OPEN_LOOP)){
+
+       if ((pDrv2625Platdata->mnLoop == CLOSE_LOOP)
+               || (pDrv2625Platdata->mnLoop == OPEN_LOOP)) {
                mask_temp |= LOOP_MASK;
                value_temp |= (pDrv2625Platdata->mnLoop << LOOP_SHIFT);
        }
-       
-       if(value_temp != 0){
-               drv2625_set_bits(pDRV2625, 
-                       DRV2625_REG_CONTROL1, 
+
+       if (value_temp != 0)
+               drv2625_set_bits(pDRV2625, DRV2625_REG_CONTROL1, 
                        mask_temp|AUTOBRK_OK_MASK, value_temp|AUTOBRK_OK_ENABLE);
-       }
-       
+
        value_temp = 0;
-       if(actuator.mnActuatorType == ERM)
+       if (actuator.mnActuatorType == ERM)
                value_temp = LIB_ERM;
-       else if(actuator.mnActuatorType == LRA)
+       else if (actuator.mnActuatorType == LRA)
                value_temp = LIB_LRA;
-       if(value_temp != 0){
-               drv2625_set_bits(pDRV2625, 
-                       DRV2625_REG_CONTROL2, LIB_MASK, value_temp<<LIB_SHIFT);
-       }
-               
-       if(actuator.mnRatedVoltage != 0){
-               drv2625_reg_write(pDRV2625, 
-                       DRV2625_REG_RATED_VOLTAGE, actuator.mnRatedVoltage);
-       }else{
-               dev_err(pDRV2625->dev, 
-                       "%s, ERROR Rated ZERO\n", __FUNCTION__);
-       }
+       if (value_temp != 0)
+               drv2625_set_bits(pDRV2625, DRV2625_REG_CONTROL2, LIB_MASK, value_temp<<LIB_SHIFT);
 
-       if(actuator.mnOverDriveClampVoltage != 0){
-               drv2625_reg_write(pDRV2625, 
-                       DRV2625_REG_OVERDRIVE_CLAMP, actuator.mnOverDriveClampVoltage);
-       }else{
-               dev_err(pDRV2625->dev,
-                       "%s, ERROR OverDriveVol ZERO\n", __FUNCTION__);
-       }
-               
-       if(actuator.mnActuatorType == LRA){
+       if (actuator.mnRatedVoltage != 0)
+               drv2625_reg_write(pDRV2625, DRV2625_REG_RATED_VOLTAGE, actuator.mnRatedVoltage);
+       else
+               dev_err(pDRV2625->dev, "%s, ERROR Rated ZERO\n", __func__);
+
+       if (actuator.mnOverDriveClampVoltage != 0)
+               drv2625_reg_write(pDRV2625, DRV2625_REG_OVERDRIVE_CLAMP, actuator.mnOverDriveClampVoltage);
+       else
+               dev_err(pDRV2625->dev,"%s, ERROR OverDriveVol ZERO\n", __func__);
+
+
+       if (actuator.mnActuatorType == LRA) {
                unsigned char DriveTime = 5*(1000 - actuator.mnLRAFreq)/actuator.mnLRAFreq;
-               unsigned short openLoopPeriod = 
+               unsigned short openLoopPeriod =
                        (unsigned short)((unsigned int)1000000000 / (24619 * actuator.mnLRAFreq)); 
-                       
-               if(actuator.mnLRAFreq < 125) 
+
+               if (actuator.mnLRAFreq < 125) 
                        DriveTime |= (MINFREQ_SEL_45HZ << MINFREQ_SEL_SHIFT);
-               drv2625_set_bits(pDRV2625, 
-                       DRV2625_REG_DRIVE_TIME, 
-                       DRIVE_TIME_MASK | MINFREQ_SEL_MASK, DriveTime); 
-               drv2625_set_bits(pDRV2625, 
-                       DRV2625_REG_OL_PERIOD_H, 0x03, (openLoopPeriod&0x0300)>>8);                     
-               drv2625_reg_write(pDRV2625, 
-                       DRV2625_REG_OL_PERIOD_L, (openLoopPeriod&0x00ff));
-               
-               dev_info(pDRV2625->dev,
-                       "%s, LRA = %d, DriveTime=0x%x\n", 
-                       __FUNCTION__, actuator.mnLRAFreq, DriveTime);
-       }       
+               drv2625_set_bits(pDRV2625, DRV2625_REG_DRIVE_TIME,
+                       DRIVE_TIME_MASK | MINFREQ_SEL_MASK, DriveTime);
+               drv2625_set_bits(pDRV2625, DRV2625_REG_OL_PERIOD_H, 0x03, (openLoopPeriod&0x0300)>>8);
+               drv2625_reg_write(pDRV2625, DRV2625_REG_OL_PERIOD_L, (openLoopPeriod&0x00ff));
+
+               dev_info(pDRV2625->dev, "%s, LRA = %d, DriveTime=0x%x\n", 
+                       __func__, actuator.mnLRAFreq, DriveTime);
+       }
 }
 
 static irqreturn_t drv2625_irq_handler(int irq, void *dev_id)
 {
        struct drv2625_data *pDRV2625 = (struct drv2625_data *)dev_id;
-       
+
        pDRV2625->mnWorkMode |= WORK_IRQ;
        schedule_work(&pDRV2625->vibrator_work);
        return IRQ_HANDLED;
 }
 
-static int drv2625_parse_dt(struct device *dev,
-                       struct drv2625_data *pDRV2625)
+static int drv2625_parse_dt(struct device *dev, struct drv2625_data *pDRV2625)
 {
        struct device_node *np = dev->of_node;
        struct drv2625_platform_data *pPlatData = &pDRV2625->msPlatData;
-       int rc= 0, ret = 0;
+       int rc= 0, nResult = 0;
        unsigned int value;
-       
+
        pPlatData->mnGpioNRST = of_get_named_gpio(np, "ti,reset-gpio", 0);
        if (pPlatData->mnGpioNRST < 0) {
                dev_err(pDRV2625->dev, "Looking up %s property in node %s failed %d\n",
-                       "ti,reset-gpio", np->full_name,
-                       pPlatData->mnGpioNRST);
-               ret = -1;
-       }else{
+                       "ti,reset-gpio", np->full_name, pPlatData->mnGpioNRST);
+               nResult = -EINVAL;
+       } else
                dev_dbg(pDRV2625->dev, "ti,reset-gpio=%d\n", pPlatData->mnGpioNRST);
-       }
-       
-       if(ret >=0){
-               pPlatData->mnGpioINT = of_get_named_gpio(np, "ti,irq-gpio", 0);
-               if (pPlatData->mnGpioINT < 0) {
-                       dev_err(pDRV2625->dev, "Looking up %s property in node %s failed %d\n",
-                               "ti,irq-gpio", np->full_name,
-                               pPlatData->mnGpioINT);
-                       ret = -1;
-               }else{
-                       dev_dbg(pDRV2625->dev, "ti,irq-gpio=%d\n", pPlatData->mnGpioINT);
-               }
-       }
-       
-       if(ret >=0){
+
+       if (nResult >=0) {
                rc = of_property_read_u32(np, "ti,smart-loop", &value);
                if (rc) {
                        dev_err(pDRV2625->dev, "Looking up %s property in node %s failed %d\n",
                                "ti,smart-loop", np->full_name, rc);
-                       ret = -2;
-               }else{
-                       pPlatData->mnLoop = value&0x01;
-                       dev_dbg(pDRV2625->dev, 
-                               "ti,smart-loop=%d\n", pPlatData->mnLoop);
+                       nResult = -EINVAL;
+               } else {
+                       pPlatData->mnLoop = value & 0x01;
+                       dev_dbg(pDRV2625->dev, "ti,smart-loop=%d\n", pPlatData->mnLoop);
                }
-       }       
-       
-       if(ret >=0){
+       }
+
+       if (nResult >=0) {
                rc = of_property_read_u32(np, "ti,actuator", &value);
                if (rc) {
                        dev_err(pDRV2625->dev, "Looking up %s property in node %s failed %d\n",
                                "ti,actuator", np->full_name, rc);
-                       ret = -2;
-               }else{
-                       pPlatData->msActuator.mnActuatorType = value&0x01;
-                       dev_dbg(pDRV2625->dev, 
-                               "ti,actuator=%d\n", pPlatData->msActuator.mnActuatorType);
+                       nResult = -EINVAL;
+               } else {
+                       pPlatData->msActuator.mnActuatorType = value & 0x01;
+                       dev_dbg(pDRV2625->dev, "ti,actuator=%d\n",
+                               pPlatData->msActuator.mnActuatorType);
                }
        }
-               
-       if(ret >=0){
+
+       if (nResult >=0) {
                rc = of_property_read_u32(np, "ti,rated-voltage", &value);
                if (rc) {
                        dev_err(pDRV2625->dev, "Looking up %s property in node %s failed %d\n",
                                "ti,rated-voltage", np->full_name, rc);
-                       ret = -2;
+                       nResult = -EINVAL;
                }else{
                        pPlatData->msActuator.mnRatedVoltage = value;
-                       dev_dbg(pDRV2625->dev, 
-                               "ti,rated-voltage=0x%x\n", pPlatData->msActuator.mnRatedVoltage);
+                       dev_dbg(pDRV2625->dev, "ti,rated-voltage=0x%x\n",
+                               pPlatData->msActuator.mnRatedVoltage);
                }
        }
-       
-       if(ret >=0){
+
+       if (nResult >=0) {
                rc = of_property_read_u32(np, "ti,odclamp-voltage", &value);
                if (rc) {
                        dev_err(pDRV2625->dev, "Looking up %s property in node %s failed %d\n",
                                "ti,odclamp-voltage", np->full_name, rc);
-                       ret = -2;
-               }else{
+                       nResult = -EINVAL;
+               } else {
                        pPlatData->msActuator.mnOverDriveClampVoltage = value;
-                       dev_dbg(pDRV2625->dev, 
-                               "ti,odclamp-voltage=0x%x\n", 
+                       dev_dbg(pDRV2625->dev, "ti,odclamp-voltage=0x%x\n", 
                                pPlatData->msActuator.mnOverDriveClampVoltage);
                }
        }
-       
-       if((ret >=0)&&(pPlatData->msActuator.mnActuatorType == LRA)){
+
+       if ((nResult >= 0) && (pPlatData->msActuator.mnActuatorType == LRA)) {
                rc = of_property_read_u32(np, "ti,lra-frequency", &value);
                if (rc) {
                        dev_err(pDRV2625->dev, "Looking up %s property in node %s failed %d\n",
                                "ti,lra-frequency", np->full_name, rc);
-                       ret = -3;
-               }else{
-                       if((value >= 45) &&(value <= 300)){
+                       nResult = -EINVAL;
+               } else {
+                       if ((value >= 45) && (value <= 300)) {
                                pPlatData->msActuator.mnLRAFreq = value;
-                               dev_dbg(pDRV2625->dev, 
-                                       "ti,lra-frequency=%d\n", 
+                               dev_dbg(pDRV2625->dev, "ti,lra-frequency=%d\n",
+                                       pPlatData->msActuator.mnLRAFreq);
+                       } else {
+                               nResult = -EINVAL;
+                               dev_err(pDRV2625->dev, "ERROR, ti,lra-frequency=%d, out of range\n", 
                                        pPlatData->msActuator.mnLRAFreq);
-                       }else{
-                               ret = -1;
-                               dev_err(pDRV2625->dev, 
-                                       "ERROR, ti,lra-frequency=%d, out of range\n", 
-                                       pPlatData->msActuator.mnLRAFreq);                               
                        }
                }
        }
-       
-       return ret;
+
+       if (nResult >= 0) {
+               pPlatData->mnGpioINT = of_get_named_gpio(np, "ti,irq-gpio", 0);
+               if (pPlatData->mnGpioINT < 0) {
+                       dev_err(pDRV2625->dev, "Looking up %s property in node %s failed %d\n",
+                               "ti,irq-gpio", np->full_name, pPlatData->mnGpioINT);
+               } else
+                       dev_dbg(pDRV2625->dev, "ti,irq-gpio=%d\n", pPlatData->mnGpioINT);
+       }
+
+       return nResult;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int drv2625_suspend(struct device *dev)
+{
+       struct drv2625_data *pDRV2625 = dev_get_drvdata(dev);
+
+       dev_dbg(pDRV2625->dev, "%s\n", __func__);
+       mutex_lock(&pDRV2625->lock);
+       if (hrtimer_active(&pDRV2625->timer) || pDRV2625->mnVibratorPlaying)
+               drv2625_stop(pDRV2625);
+       mutex_unlock(&pDRV2625->lock);
+
+       return 0;
+}
+
+static int drv2625_resume(struct device *dev)
+{
+       return 0; 
+}
+#endif
+
 static struct regmap_config drv2625_i2c_regmap = {
        .reg_bits = 8,
        .val_bits = 8,
        .cache_type = REGCACHE_NONE,
-       .max_register = 0xff,
 };
 
 static int drv2625_i2c_probe(struct i2c_client* client, const struct i2c_device_id* id)
 {
        struct drv2625_data *pDRV2625;
-       int err = 0;
+       int nResult = 0;
 
-       dev_info(&client->dev, "%s enter\n", __FUNCTION__);
-       
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
-       {
-               dev_err(&client->dev, "%s:I2C check failed\n", __FUNCTION__);
+       dev_info(&client->dev, "%s enter\n", __func__);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               dev_err(&client->dev, "%s:I2C check failed\n", __func__);
                return -ENODEV;
        }
 
        pDRV2625 = devm_kzalloc(&client->dev, sizeof(struct drv2625_data), GFP_KERNEL);
-       if (pDRV2625 == NULL){
-               dev_err(&client->dev, "%s:no memory\n", __FUNCTION__);
+       if (pDRV2625 == NULL) {
+               dev_err(&client->dev, "%s:no memory\n", __func__);
                return -ENOMEM;
        }
 
        pDRV2625->dev = &client->dev;
        i2c_set_clientdata(client,pDRV2625);
        dev_set_drvdata(&client->dev, pDRV2625);
-       
+
        pDRV2625->mpRegmap = devm_regmap_init_i2c(client, &drv2625_i2c_regmap);
        if (IS_ERR(pDRV2625->mpRegmap)) {
-               err = PTR_ERR(pDRV2625->mpRegmap);
-               dev_err(pDRV2625->dev, 
-                       "%s:Failed to allocate register map: %d\n",__FUNCTION__,err);
-               return err;
+               nResult = PTR_ERR(pDRV2625->mpRegmap);
+               dev_err(pDRV2625->dev, "%s:Failed to allocate register map: %d\n",
+                       __func__, nResult);
+               return nResult;
        }
 
-       if (client->dev.of_node){
+       if (client->dev.of_node) {
                dev_dbg(pDRV2625->dev, "of node parse\n");
-               err = drv2625_parse_dt(&client->dev, pDRV2625);
-       }else if(client->dev.platform_data){
+               nResult = drv2625_parse_dt(&client->dev, pDRV2625);
+       } else if (client->dev.platform_data) {
                dev_dbg(pDRV2625->dev, "platform data parse\n");
-               memcpy(&pDRV2625->msPlatData, 
-                       client->dev.platform_data, sizeof(struct drv2625_platform_data));
-       }else{
-               dev_err(pDRV2625->dev, 
-                       "%s: ERROR no platform data\n",__FUNCTION__);
-               return -1;
+               memcpy(&pDRV2625->msPlatData, client->dev.platform_data,
+                       sizeof(struct drv2625_platform_data));
+       } else {
+               dev_err(pDRV2625->dev, "%s: ERROR no platform data\n",__func__);
+               return -EINVAL;
        }
-       
-       if((err < 0)
-               ||(pDRV2625->msPlatData.mnGpioNRST <= 0)
-               ||(pDRV2625->msPlatData.mnGpioINT <= 0)){
-               dev_err(pDRV2625->dev, 
-                       "%s: platform data error\n",__FUNCTION__);
-               return -1;              
+
+       if ((nResult < 0) || !gpio_is_valid(pDRV2625->msPlatData.mnGpioNRST)) {
+               dev_err(pDRV2625->dev, "%s: platform data error\n",__func__);
+               return -EINVAL;
        }
-               
-       if(pDRV2625->msPlatData.mnGpioNRST){
-               err = gpio_request(pDRV2625->msPlatData.mnGpioNRST,"DRV2625-NRST");
-               if(err < 0){
-                       dev_err(pDRV2625->dev, 
-                               "%s: GPIO %d request NRST error\n", 
-                               __FUNCTION__, pDRV2625->msPlatData.mnGpioNRST);                         
-                       return err;
+
+       if (gpio_is_valid(pDRV2625->msPlatData.mnGpioNRST)) {
+               nResult = gpio_request(pDRV2625->msPlatData.mnGpioNRST,"DRV2625-NRST");
+               if (nResult < 0) {
+                       dev_err(pDRV2625->dev, "%s: GPIO %d request NRST error\n",
+                               __func__, pDRV2625->msPlatData.mnGpioNRST);
+                       return nResult;
                }
-               
+
                gpio_direction_output(pDRV2625->msPlatData.mnGpioNRST, 0);
                mdelay(5);
                gpio_direction_output(pDRV2625->msPlatData.mnGpioNRST, 1);
                mdelay(2);
        }
 
-       err = drv2625_reg_read(pDRV2625, DRV2625_REG_ID);
-       if(err < 0){
-               dev_err(pDRV2625->dev, 
-                       "%s, i2c bus fail (%d)\n", __FUNCTION__, err);
+       mutex_init(&pDRV2625->dev_lock);
+       nResult = drv2625_reg_read(pDRV2625, DRV2625_REG_ID);
+       if (nResult < 0)
                goto exit_gpio_request_failed1;
-       }else{
-               dev_info(pDRV2625->dev, 
-                       "%s, ID status (0x%x)\n", __FUNCTION__, err);
-               pDRV2625->mnDeviceID = err;
+       else {
+               dev_info(pDRV2625->dev, "%s, ID status (0x%x)\n", __func__, nResult);
+               pDRV2625->mnDeviceID = nResult;
        }
-       
-       if((pDRV2625->mnDeviceID&0xf0) != DRV2625_ID){
-               dev_err(pDRV2625->dev, 
-                       "%s, device_id(0x%x) fail\n",
-                       __FUNCTION__, pDRV2625->mnDeviceID);
+
+       if ((pDRV2625->mnDeviceID & 0xf0) != DRV2625_ID) {
+               dev_err(pDRV2625->dev, "%s, device_id(0x%x) fail\n",
+                       __func__, pDRV2625->mnDeviceID);
                goto exit_gpio_request_failed1;
        }
-       
+
        dev_init_platform_data(pDRV2625);
 
-       if(pDRV2625->msPlatData.mnGpioINT){
-               err = gpio_request(pDRV2625->msPlatData.mnGpioINT, "DRV2625-IRQ");
-               if(err < 0){
-                       dev_err(pDRV2625->dev, 
-                               "%s: GPIO %d request INT error\n", 
-                               __FUNCTION__, pDRV2625->msPlatData.mnGpioINT);                                  
+       if (gpio_is_valid(pDRV2625->msPlatData.mnGpioINT)) {
+               nResult = gpio_request(pDRV2625->msPlatData.mnGpioINT, "DRV2625-IRQ");
+               if (nResult < 0) {
+                       dev_err(pDRV2625->dev, "%s: GPIO %d request INT error\n",
+                               __func__, pDRV2625->msPlatData.mnGpioINT);
                        goto exit_gpio_request_failed1;
                }
-
                gpio_direction_input(pDRV2625->msPlatData.mnGpioINT);
-
                pDRV2625->mnIRQ = gpio_to_irq(pDRV2625->msPlatData.mnGpioINT);
                dev_dbg(pDRV2625->dev, "irq = %d \n", pDRV2625->mnIRQ);
-               
-               err = request_threaded_irq(pDRV2625->mnIRQ, drv2625_irq_handler,
-                               NULL, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-                               client->name, pDRV2625);
 
-               if (err < 0) {
-                       dev_err(pDRV2625->dev, 
-                               "request_irq failed, %d\n", err);                                                       
+               nResult = request_threaded_irq(pDRV2625->mnIRQ, drv2625_irq_handler,
+                               NULL, IRQF_TRIGGER_FALLING | IRQF_ONESHOT, client->name, pDRV2625);
+               if (nResult < 0) {
+                       dev_err(pDRV2625->dev, "request_irq failed, %d\n", nResult);
                        goto exit_gpio_request_failed2;
                }
-               drv2625_disableIRQ(pDRV2625);
-       }
+               disable_irq_nosync(pDRV2625->mnIRQ);
+               pDRV2625->mbIRQEnabled = false;
+               pDRV2625->mbIRQUsed = true;
+       } else
+               pDRV2625->mbIRQUsed = false;
 
        g_DRV2625data = pDRV2625;
-       
-    Haptics_init(pDRV2625);
 
-       
-#ifdef AUTOCALIBRATION_ENABLE  
-       drv2625_enableIRQ(pDRV2625, NO);
-       err = dev_auto_calibrate(pDRV2625);
-       if(err < 0){
-               dev_err(pDRV2625->dev, 
-                       "%s, ERROR, calibration fail\n",        
-                       __FUNCTION__);
-       }
-#endif
-       
-    dev_info(pDRV2625->dev, 
-               "drv2625 probe succeeded\n");
+       Haptics_init(pDRV2625);
+
+       dev_info(pDRV2625->dev, "drv2625 probe succeeded\n");
 
-    return 0;
+       return 0;
 
 exit_gpio_request_failed2:
-       if(pDRV2625->msPlatData.mnGpioINT > 0){
+       if (gpio_is_valid(pDRV2625->msPlatData.mnGpioINT))
                gpio_free(pDRV2625->msPlatData.mnGpioINT);
-       }
-       
-exit_gpio_request_failed1:     
-       if(pDRV2625->msPlatData.mnGpioNRST > 0){
+
+exit_gpio_request_failed1:
+       if (gpio_is_valid(pDRV2625->msPlatData.mnGpioNRST))
                gpio_free(pDRV2625->msPlatData.mnGpioNRST);
-       }
 
-    dev_err(pDRV2625->dev, 
-               "%s failed, err=%d\n",
-               __FUNCTION__, err);
-       return err;
+       mutex_destroy(&pDRV2625->dev_lock);
+
+       dev_err(pDRV2625->dev, "%s failed, err=%d\n", __func__, nResult);
+       return nResult;
 }
 
 static int drv2625_i2c_remove(struct i2c_client* client)
@@ -1222,8 +1355,11 @@ static int drv2625_i2c_remove(struct i2c_client* client)
                gpio_free(pDRV2625->msPlatData.mnGpioINT);
 
        misc_deregister(&drv2625_misc);
-       
-    return 0;
+
+       mutex_destroy(&pDRV2625->lock);
+       mutex_destroy(&pDRV2625->dev_lock);
+
+       return 0;
 }
 
 static const struct i2c_device_id drv2625_i2c_id[] = {
@@ -1231,6 +1367,12 @@ static const struct i2c_device_id drv2625_i2c_id[] = {
        {}
 };
 
+#ifdef CONFIG_PM_SLEEP
+static const struct dev_pm_ops drv2625_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(drv2625_suspend, drv2625_resume)
+};
+#endif
+
 MODULE_DEVICE_TABLE(i2c, drv2625_i2c_id);
 
 #if defined(CONFIG_OF)
@@ -1246,6 +1388,9 @@ static struct i2c_driver drv2625_i2c_driver = {
        .driver = {
                        .name = "drv2625",
                        .owner = THIS_MODULE,
+#ifdef CONFIG_PM_SLEEP
+                       .pm = &drv2625_pm_ops,
+#endif
 #if defined(CONFIG_OF)
                        .of_match_table = of_match_ptr(drv2625_of_match),
 #endif
@@ -1259,4 +1404,4 @@ module_i2c_driver(drv2625_i2c_driver);
 
 MODULE_AUTHOR("Texas Instruments Inc.");
 MODULE_DESCRIPTION("DRV2625 I2C Smart Haptics driver");
-MODULE_LICENSE("GPLv2");
\ No newline at end of file
+MODULE_LICENSE("GPL v2");
\ No newline at end of file
index 2c9affede4c5f79c384cea5bb0534cd3bafc9ce7..50d86b4d96045f3d3501e3f50d1fa1b9708166f1 100755 (executable)
--- a/drv2625.h
+++ b/drv2625.h
 
 #define        DRV2625_REG_DIAG_K                      0x30
 
-#define GO_BIT_POLL_INTERVAL    15
-#define STANDBY_WAKE_DELAY      1
-#define WAKE_STANDBY_DELAY      3
+#define        GO_BIT_POLL_INTERVAL    15
+#define        STANDBY_WAKE_DELAY              1
+#define        WAKE_STANDBY_DELAY              3
+
 
 /* Commands */
-#define HAPTIC_CMDID_PLAY_SINGLE_EFFECT     0x01
-#define HAPTIC_CMDID_PLAY_EFFECT_SEQUENCE   0x02
-#define HAPTIC_CMDID_PLAY_TIMED_EFFECT      0x03
-#define HAPTIC_CMDID_GET_DEV_ID             0x04
-#define HAPTIC_CMDID_RUN_DIAG               0x05
-#define HAPTIC_CMDID_AUDIOHAPTIC_ENABLE     0x06
-#define HAPTIC_CMDID_AUDIOHAPTIC_DISABLE    0x07
-#define HAPTIC_CMDID_AUDIOHAPTIC_GETSTATUS  0x08
-
-#define HAPTIC_CMDID_REG_WRITE         0x09
-#define HAPTIC_CMDID_REG_READ          0x0a
-#define HAPTIC_CMDID_REG_SETBIT        0x0b
-
-#define HAPTIC_CMDID_PATTERN_RTP      0x0c
-#define HAPTIC_CMDID_RTP_SEQUENCE        0x0d
-#define HAPTIC_CMDID_GET_EFFECT_COUNT          0x10
-#define HAPTIC_CMDID_UPDATE_FIRMWARE           0x11
-#define HAPTIC_CMDID_READ_FIRMWARE                     0x12
-#define HAPTIC_CMDID_RUN_CALIBRATION        0x13
-#define        HAPTIC_CMDID_CONFIG_WAVEFORM            0x14
-#define        HAPTIC_CMDID_SET_SEQUENCER                      0x15
-
-#define HAPTIC_CMDID_STOP                   0xFF
-
-#define MAX_TIMEOUT    10000 /* 10s */
+#define        HAPTIC_CMDID_PLAY_SINGLE_EFFECT         0x01
+#define        HAPTIC_CMDID_PLAY_EFFECT_SEQUENCE       0x02
+#define        HAPTIC_CMDID_PLAY_TIMED_EFFECT          0x03
+#define        HAPTIC_CMDID_GET_DEV_ID                         0x04
+#define        HAPTIC_CMDID_RUN_DIAG                           0x05
+#define        HAPTIC_CMDID_AUDIOHAPTIC_ENABLE         0x06
+#define        HAPTIC_CMDID_AUDIOHAPTIC_DISABLE        0x07
+#define        HAPTIC_CMDID_AUDIOHAPTIC_GETSTATUS      0x08
+#define        HAPTIC_CMDID_REG_WRITE                          0x09
+#define        HAPTIC_CMDID_REG_READ                           0x0a
+#define        HAPTIC_CMDID_REG_SETBIT                         0x0b
+#define        HAPTIC_CMDID_PATTERN_RTP                        0x0c
+#define        HAPTIC_CMDID_RTP_SEQUENCE                       0x0d
+#define        HAPTIC_CMDID_GET_EFFECT_COUNT           0x10
+#define        HAPTIC_CMDID_UPDATE_FIRMWARE            0x11
+#define        HAPTIC_CMDID_READ_FIRMWARE                      0x12
+#define        HAPTIC_CMDID_RUN_CALIBRATION            0x13
+#define        HAPTIC_CMDID_CONFIG_WAVEFORM            0x14
+#define        HAPTIC_CMDID_SET_SEQUENCER                      0x15
+#define        HAPTIC_CMDID_REGLOG_ENABLE                      0x16
+
+#define        HAPTIC_CMDID_STOP               0xFF
+
+#define        MAX_TIMEOUT             10000 /* 10s */
 #define        MAX_READ_BYTES  0xff
 #define        DRV2625_SEQUENCER_SIZE  8
 
 #define        WORK_IDLE                                       0
 #define        WORK_VIBRATOR                           0x01
 #define        WORK_IRQ                                        0x02
+#define        WORK_EFFECTSEQUENCER            0x04
+#define        WORK_CALIBRATION                        0x08
+#define        WORK_DIAGNOSTIC                         0x10
 
 #define        YES             1
-#define NO             0
+#define        NO              0
 #define        GO              1
-#define STOP   0
+#define        STOP    0
 
+#define        POLL_GO_BIT_INTERVAL    5       /* 5 ms */
+#define        POLL_GO_BIT_RETRY               20      /* 50 times */
 
 enum actuator_type {
        ERM,
@@ -178,7 +183,7 @@ struct actuator_data {
        unsigned char mnActuatorType;
        unsigned char mnRatedVoltage;
        unsigned char mnOverDriveClampVoltage;
-       unsigned char mnLRAFreq;        
+       unsigned char mnLRAFreq;
 };
 
 enum wave_seq_loop {
@@ -213,7 +218,7 @@ enum wave_main_interval {
 
 struct drv2625_waveform {
        unsigned char mnEffect;
-       unsigned char mnLoop;   
+       unsigned char mnLoop;
 };
 
 struct drv2625_waveform_sequencer {
@@ -223,7 +228,7 @@ struct drv2625_waveform_sequencer {
 struct drv2625_wave_setting {
        unsigned char mnLoop;
        unsigned char mnInterval;
-       unsigned char mnScale;  
+       unsigned char mnScale;
 };
 
 struct drv2625_autocal_result {
@@ -242,31 +247,34 @@ struct drv2625_diag_result {
 };
 
 struct drv2625_platform_data {
-       int     mnGpioNRST;
-       int     mnGpioINT;
+       int mnGpioNRST;
+       int mnGpioINT;
        unsigned char mnLoop; 
        struct actuator_data msActuator;
 };
 
 struct drv2625_data {
        struct drv2625_platform_data msPlatData;
+       struct mutex dev_lock;
        unsigned char mnDeviceID;
        struct device *dev;
        struct regmap *mpRegmap;
        unsigned int mnIRQ;
        unsigned char mnIntStatus;
+       bool mbIRQEnabled;
+       bool mbIRQUsed;
        struct drv2625_wave_setting msWaveformSetting;
        struct drv2625_waveform_sequencer msWaveformSequencer;  
        unsigned char mnFileCmd;
        volatile int mnVibratorPlaying;
        volatile char mnWorkMode;
        unsigned char mnCurrentReg;
-    struct wake_lock wklock;
-    struct hrtimer timer;
-    struct mutex lock;
-    struct work_struct vibrator_work;
-       struct timed_output_dev to_dev; 
-       
+       struct wake_lock wklock;
+       struct hrtimer timer;
+       struct mutex lock;
+       struct work_struct vibrator_work;
+       struct timed_output_dev to_dev;
+
        struct drv2625_autocal_result mAutoCalResult;
        struct drv2625_diag_result mDiagResult;
 };