3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License.
8 #include <linux/kernel.h>
9 #include <linux/device.h>
10 #include <linux/completion.h>
11 #include <linux/delay.h>
12 #include <linux/err.h>
13 #include <linux/adc.h>
16 static struct adc_host *g_adc = NULL;
18 struct adc_host *adc_alloc_host(int extra, struct device *dev)
22 adc = kzalloc(sizeof(struct adc_host) + extra, GFP_KERNEL);
29 EXPORT_SYMBOL(adc_alloc_host);
30 void adc_free_host(struct adc_host *adc)
36 EXPORT_SYMBOL(adc_free_host);
39 struct adc_client *adc_register(int chn,
40 void (*callback)(struct adc_client *, void *, int),
43 struct adc_client *client;
46 printk(KERN_ERR "adc host has not initialized\n");
49 if(chn >= MAX_ADC_CHN)
51 dev_err(g_adc->dev, "channel[%d] is greater than the maximum[%d]\n", chn, MAX_ADC_CHN);
54 client = kzalloc(sizeof(struct adc_client), GFP_KERNEL);
57 dev_err(g_adc->dev, "no memory for adc client\n");
60 client->callback = callback;
61 client->callback_param = callback_param;
68 EXPORT_SYMBOL(adc_register);
70 void adc_unregister(struct adc_client *client)
76 EXPORT_SYMBOL(adc_unregister);
79 static void trigger_next_adc_job_if_any(struct adc_host *adc)
81 int head = adc->queue_head;
83 if (!adc->queue[head])
85 adc->cur = adc->queue[head]->client;
91 adc_enqueue_request(struct adc_host *adc, struct adc_request *req)
96 spin_lock_irqsave(&adc->lock, flags);
97 head = adc->queue_head;
98 tail = adc->queue_tail;
100 if (adc->queue[tail]) {
101 spin_unlock_irqrestore(&adc->lock,flags);
102 dev_err(adc->dev, "ADC queue is full, dropping request\n");
106 adc->queue[tail] = req;
108 trigger_next_adc_job_if_any(adc);
109 adc->queue_tail = (tail + 1) & (MAX_ADC_FIFO_DEPTH - 1);
111 spin_unlock_irqrestore(&adc->lock,flags);
117 adc_sync_read_callback(struct adc_client *client, void *param, int result)
119 struct adc_request *req = param;
121 client->result = result;
122 complete(&req->completion);
125 int adc_sync_read(struct adc_client *client)
127 struct adc_request *req = NULL;
131 printk(KERN_ERR "client point is NULL");
134 if(client->adc->is_suspended == 1) {
135 dev_dbg(client->adc->dev, "system enter sleep\n");
138 req = kzalloc(sizeof(*req), GFP_ATOMIC);
140 dev_err(client->adc->dev, "no memory for adc request\n");
143 req->chn = client->chn;
144 req->callback = adc_sync_read_callback;
145 req->callback_param = req;
146 req->client = client;
147 req->status = SYNC_READ;
149 init_completion(&req->completion);
150 err = adc_enqueue_request(client->adc, req);
153 dev_err(client->adc->dev, "fail to enqueue request\n");
157 tmo = wait_for_completion_timeout(&req->completion,msecs_to_jiffies(100));
161 tail = (client->adc->queue_tail - 1) & (MAX_ADC_FIFO_DEPTH - 1);
162 client->adc->queue[tail] = NULL;
163 client->adc->queue_tail = tail;
166 return client->result;
168 EXPORT_SYMBOL(adc_sync_read);
170 int adc_async_read(struct adc_client *client)
173 struct adc_request *req = NULL;
176 printk(KERN_ERR "client point is NULL");
179 if(client->adc->is_suspended == 1) {
180 dev_dbg(client->adc->dev, "system enter sleep\n");
183 req = kzalloc(sizeof(*req), GFP_ATOMIC);
185 dev_err(client->adc->dev, "no memory for adc request\n");
188 req->chn = client->chn;
189 req->callback = client->callback;
190 req->callback_param = client->callback_param;
191 req->client = client;
192 req->status = ASYNC_READ;
194 ret = adc_enqueue_request(client->adc, req);
200 EXPORT_SYMBOL(adc_async_read);
202 void adc_core_irq_handle(struct adc_host *adc)
204 struct adc_request *req;
206 spin_lock(&adc->lock);
207 head = adc->queue_head;
209 req = adc->queue[head];
211 spin_unlock(&adc->lock);
212 dev_err(adc->dev, "adc irq: ADC queue empty!\n");
215 adc->queue[head] = NULL;
216 adc->queue_head = (head + 1) & (MAX_ADC_FIFO_DEPTH - 1);
218 res = adc->ops->read(adc);
220 trigger_next_adc_job_if_any(adc);
222 req->callback(adc->cur, req->callback_param, res);
223 if(req->status == ASYNC_READ) {
227 spin_unlock(&adc->lock);
229 EXPORT_SYMBOL(adc_core_irq_handle);