mirror of
https://github.com/torvalds/linux.git
synced 2026-06-08 22:52:35 +02:00
update adc driver modify 'sync_read bug'
This commit is contained in:
parent
03f73ff658
commit
164ed84c3e
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -66,31 +66,50 @@ static const struct adc_ops rk29_adc_ops = {
|
|||
.read = rk29_adc_read,
|
||||
};
|
||||
#ifdef ADC_TEST
|
||||
struct adc_test_data {
|
||||
struct adc_client *client;
|
||||
struct timer_list timer;
|
||||
struct work_struct timer_work;
|
||||
};
|
||||
static void callback(struct adc_client *client, void *param, int result)
|
||||
{
|
||||
dev_info(client->adc->dev, "[chn%d] async_read = %d\n", client->chn, result);
|
||||
return;
|
||||
}
|
||||
static void adc_timer(unsigned long data)
|
||||
{
|
||||
//int sync_read = 0;
|
||||
struct adc_test_data *test=(struct adc_test_data *)data;
|
||||
|
||||
//sync_read = adc_sync_read(test->client);
|
||||
//dev_info(test->client->adc->dev, "[chn%d] sync_read = %d\n", 0, sync_read);
|
||||
schedule_work(&test->timer_work);
|
||||
add_timer(&test->timer);
|
||||
}
|
||||
static void adc_timer_work(struct work_struct *work)
|
||||
{
|
||||
int sync_read = 0;
|
||||
struct adc_test_data *test = container_of(work, struct adc_test_data,
|
||||
timer_work);
|
||||
adc_async_read(test->client);
|
||||
sync_read = adc_sync_read(test->client);
|
||||
dev_info(test->client->adc->dev, "[chn%d] sync_read = %d\n", 0, sync_read);
|
||||
}
|
||||
|
||||
static int rk29_adc_test(void)
|
||||
{
|
||||
int sync_read = 0, i, j = 10;
|
||||
struct adc_client *client =NULL;
|
||||
struct adc_test_data *test = NULL;
|
||||
|
||||
while(j--)
|
||||
{
|
||||
client = adc_register(i, callback, NULL);
|
||||
adc_async_read(client);
|
||||
mdelay(1000);
|
||||
sync_read = adc_sync_read(client);
|
||||
dev_info(client->adc->dev, "[chn%d] sync_read = %d\n", client->chn, sync_read);
|
||||
adc_unregister(client);
|
||||
mdelay(1000);
|
||||
i++;
|
||||
if(i >= 4)
|
||||
i = 0;
|
||||
}
|
||||
adc_unregister(client);
|
||||
test = kzalloc(sizeof(struct adc_test_data), GFP_KERNEL);
|
||||
|
||||
test->client = adc_register(0, callback, NULL);
|
||||
INIT_WORK(&test->timer_work, adc_timer_work);
|
||||
setup_timer(&test->timer, adc_timer, (unsigned long)test);
|
||||
test->timer.expires = jiffies + 100;
|
||||
add_timer(&test->timer);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -157,9 +176,6 @@ static int rk29_adc_probe(struct platform_device *pdev)
|
|||
}
|
||||
platform_set_drvdata(pdev, dev);
|
||||
dev_info(&pdev->dev, "rk29 adc: driver initialized\n");
|
||||
#ifdef ADC_TEST
|
||||
rk29_adc_test();
|
||||
#endif
|
||||
return 0;
|
||||
// err_iomap:
|
||||
// iounmap(dev->regs);
|
||||
|
|
@ -243,4 +259,12 @@ module_exit(rk29_adc_exit);
|
|||
MODULE_DESCRIPTION("Driver for ADC");
|
||||
MODULE_AUTHOR("kfx, kfx@rock-chips.com");
|
||||
MODULE_LICENSE("GPL");
|
||||
static int __init adc_test_init(void)
|
||||
{
|
||||
#ifdef ADC_TEST
|
||||
rk29_adc_test();
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
}
|
||||
module_init(adc_test_init);
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ struct adc_request {
|
|||
struct adc_client *client;
|
||||
/* Used in case of sync requests */
|
||||
struct completion completion;
|
||||
#define ASYNC_READ 0
|
||||
#define SYNC_READ 1
|
||||
int status;
|
||||
};
|
||||
struct adc_host;
|
||||
struct adc_ops {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user