update adc driver modify 'sync_read bug'
authorkfx <kfx@rock-chips.com>
Tue, 22 Mar 2011 00:46:37 +0000 (08:46 +0800)
committerkfx <kfx@rock-chips.com>
Tue, 22 Mar 2011 00:46:37 +0000 (08:46 +0800)
drivers/adc/core.c
drivers/adc/plat/rk29_adc.c
include/linux/adc.h

index 9ad1dae2e6ff192024b00a66f3322ba91345c1b1..ce00e01c1c971b4496029f9145891b078440c130 100755 (executable)
@@ -125,7 +125,7 @@ adc_sync_read_callback(struct adc_client *client, void *param, int result)
 int adc_sync_read(struct adc_client *client)
 {
        struct adc_request *req = NULL;
-       int err, tmo;
+       int err, tmo, tail;
 
        if(client == NULL) {
                printk(KERN_ERR "client point is NULL");
@@ -144,6 +144,7 @@ int adc_sync_read(struct adc_client *client)
        req->callback =  adc_sync_read_callback;
        req->callback_param = req;
        req->client = client;
+       req->status = SYNC_READ;
 
        init_completion(&req->completion);
        err = adc_enqueue_request(client->adc, req);
@@ -154,8 +155,14 @@ int adc_sync_read(struct adc_client *client)
                return err;
        }
        tmo = wait_for_completion_timeout(&req->completion,msecs_to_jiffies(100));
-       if(tmo == 0)
+       kfree(req);
+       req = NULL;
+       if(tmo == 0) {
+               tail = (client->adc->queue_tail - 1) & (MAX_ADC_FIFO_DEPTH - 1);
+               client->adc->queue[tail] = NULL;
+               client->adc->queue_tail = tail;
                return -ETIMEDOUT;
+       }
        return client->result;
 }
 EXPORT_SYMBOL(adc_sync_read);
@@ -181,6 +188,7 @@ int adc_async_read(struct adc_client *client)
        req->callback = client->callback;
        req->callback_param = client->callback_param;
        req->client = client;
+       req->status = ASYNC_READ;
 
        return adc_enqueue_request(client->adc, req);
 }
@@ -206,7 +214,10 @@ void adc_core_irq_handle(struct adc_host *adc)
        trigger_next_adc_job_if_any(adc);
 
        req->callback(adc->cur, req->callback_param, res);
-       kfree(req);
+       if(req->status == ASYNC_READ) {
+               kfree(req);
+               req = NULL;
+       }
 }
 EXPORT_SYMBOL(adc_core_irq_handle);
 
index 0ddbec28943551908f75c1df6406cb4a849fecdc..6bf01ba8c56f0df4d31b46cd0519fae83ee01058 100755 (executable)
@@ -66,31 +66,50 @@ static const struct adc_ops rk29_adc_ops = {
        .read           = rk29_adc_read,\r
 };\r
 #ifdef ADC_TEST\r
+struct adc_test_data {\r
+       struct adc_client *client;\r
+       struct timer_list timer;\r
+       struct work_struct      timer_work;\r
+};\r
 static void callback(struct adc_client *client, void *param, int result)\r
 {\r
        dev_info(client->adc->dev, "[chn%d] async_read = %d\n", client->chn, result);\r
        return;\r
 }\r
+static void adc_timer(unsigned long data)\r
+{\r
+       //int sync_read = 0;\r
+        struct adc_test_data *test=(struct adc_test_data *)data;\r
+       \r
+       //sync_read = adc_sync_read(test->client);\r
+       //dev_info(test->client->adc->dev, "[chn%d] sync_read = %d\n", 0, sync_read);\r
+       schedule_work(&test->timer_work);\r
+       add_timer(&test->timer);\r
+}\r
+static void adc_timer_work(struct work_struct *work)\r
+{      \r
+       int sync_read = 0;\r
+       struct adc_test_data *test = container_of(work, struct adc_test_data,\r
+                                               timer_work);\r
+       adc_async_read(test->client);\r
+       sync_read = adc_sync_read(test->client);\r
+       dev_info(test->client->adc->dev, "[chn%d] sync_read = %d\n", 0, sync_read);\r
+}\r
+\r
 static int rk29_adc_test(void)\r
 {\r
-       int sync_read = 0, i, j = 10;\r
-       struct adc_client *client =NULL;\r
-\r
-       while(j--)\r
-       {\r
-               client = adc_register(i, callback, NULL);\r
-               adc_async_read(client);\r
-               mdelay(1000);\r
-               sync_read = adc_sync_read(client);\r
-               dev_info(client->adc->dev, "[chn%d] sync_read = %d\n", client->chn, sync_read);\r
-               adc_unregister(client);\r
-               mdelay(1000);\r
-               i++;\r
-               if(i >= 4)\r
-                       i = 0;\r
-       }\r
-       adc_unregister(client);\r
+       struct adc_test_data *test = NULL;\r
+\r
+       test = kzalloc(sizeof(struct adc_test_data), GFP_KERNEL);\r
+       \r
+       test->client = adc_register(0, callback, NULL);\r
+       INIT_WORK(&test->timer_work, adc_timer_work);\r
+       setup_timer(&test->timer, adc_timer, (unsigned long)test);\r
+       test->timer.expires  = jiffies + 100;\r
+       add_timer(&test->timer);\r
+       \r
        return 0;\r
+\r
 }\r
 #endif\r
 \r
@@ -157,9 +176,6 @@ static int rk29_adc_probe(struct platform_device *pdev)
        }\r
        platform_set_drvdata(pdev, dev);\r
        dev_info(&pdev->dev, "rk29 adc: driver initialized\n");\r
-#ifdef ADC_TEST        \r
-       rk29_adc_test();\r
-#endif\r
        return 0;\r
 // err_iomap:\r
 //     iounmap(dev->regs);\r
@@ -243,4 +259,12 @@ module_exit(rk29_adc_exit);
 MODULE_DESCRIPTION("Driver for ADC");\r
 MODULE_AUTHOR("kfx, kfx@rock-chips.com");\r
 MODULE_LICENSE("GPL");\r
+static int __init adc_test_init(void)\r
+{\r
+#ifdef ADC_TEST        \r
+               rk29_adc_test();\r
+#endif\r
+       return 0;\r
 \r
+}\r
+module_init(adc_test_init);\r
index fcef9923f78bb0579079d31656edf19b915f3750..d9ed72afbe0ffe18a3f9e0a5fa1a90fefc22dbed 100755 (executable)
@@ -31,6 +31,9 @@ struct adc_request {
        struct adc_client *client;\r
        /* Used in case of sync requests */\r
        struct completion completion;\r
+#define ASYNC_READ 0\r
+#define SYNC_READ 1\r
+       int status;\r
 };\r
 struct adc_host;\r
 struct adc_ops {\r