update from 29 server
[firefly-linux-kernel-4.4.55.git] / drivers / adc / core.c
1 /* drivers/adc/core.c
2  *
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.
6 */
7
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>
14
15
16 static struct adc_host *g_adc = NULL;
17
18 struct adc_host *adc_alloc_host(int extra, struct device *dev)
19 {
20         struct adc_host *adc;
21         
22         adc = kzalloc(sizeof(struct adc_host) + extra, GFP_KERNEL);
23         if (!adc)
24                 return NULL;
25         adc->dev = dev;
26         g_adc = adc;
27         return adc;
28 }
29 EXPORT_SYMBOL(adc_alloc_host);
30 void adc_free_host(struct adc_host *adc)
31 {
32         kfree(adc);
33         adc = NULL;
34         return;
35 }
36 EXPORT_SYMBOL(adc_free_host);
37
38
39 struct adc_client *adc_register(int chn,
40                                 void (*callback)(struct adc_client *, void *, int), 
41                                 void *callback_param)
42 {
43         struct adc_client *client;
44         if(!g_adc)
45         {
46                 printk(KERN_ERR "adc host has not initialized\n");
47                 return NULL;
48         }
49         if(chn >= MAX_ADC_CHN)
50         {
51                 dev_err(g_adc->dev, "channel[%d] is greater than the maximum[%d]\n", chn, MAX_ADC_CHN);
52                 return NULL;
53         }
54         client = kzalloc(sizeof(struct adc_client), GFP_KERNEL);
55         if(!client)
56         {
57                 dev_err(g_adc->dev, "no memory for adc client\n");
58                 return NULL;
59         }
60         client->callback = callback;
61         client->callback_param = callback_param;
62         client->chn = chn;
63
64         client->adc = g_adc;
65
66         return client;
67 }
68 EXPORT_SYMBOL(adc_register);
69
70 void adc_unregister(struct adc_client *client)
71 {
72         kfree(client);
73         client = NULL;
74         return;
75 }
76 EXPORT_SYMBOL(adc_unregister);
77
78
79 static void trigger_next_adc_job_if_any(struct adc_host *adc)
80 {
81         int head = adc->queue_head;
82
83         if (!adc->queue[head])
84                 return;
85         adc->cur = adc->queue[head]->client;
86         adc->ops->start(adc);
87         return;
88 }
89
90 static int
91 adc_enqueue_request(struct adc_host *adc, struct adc_request *req)
92 {
93         int head, tail;
94         unsigned long flags;
95         
96         spin_lock_irqsave(&adc->lock, flags);
97         head = adc->queue_head;
98         tail = adc->queue_tail;
99
100         if (adc->queue[tail]) {
101                 spin_unlock_irqrestore(&adc->lock,flags);
102                 dev_err(adc->dev, "ADC queue is full, dropping request\n");
103                 return -EBUSY;
104         }
105
106         adc->queue[tail] = req;
107         if (head == tail)
108                 trigger_next_adc_job_if_any(adc);
109         adc->queue_tail = (tail + 1) & (MAX_ADC_FIFO_DEPTH - 1);
110
111         spin_unlock_irqrestore(&adc->lock,flags);
112
113         return 0;
114 }
115
116 static void
117 adc_sync_read_callback(struct adc_client *client, void *param, int result)
118 {
119         struct adc_request *req = param;
120
121         client->result = result;
122         complete(&req->completion);
123 }
124
125 int adc_sync_read(struct adc_client *client)
126 {
127         struct adc_request *req = NULL;
128         int err, tmo, tail;
129
130         if(client == NULL) {
131                 printk(KERN_ERR "client point is NULL");
132                 return -EINVAL;
133         }
134         if(client->adc->is_suspended == 1) {
135                 dev_dbg(client->adc->dev, "system enter sleep\n");
136                 return -1;
137         }
138         req = kzalloc(sizeof(*req), GFP_ATOMIC);
139         if (!req){
140                 dev_err(client->adc->dev, "no memory for adc request\n");
141                 return -ENOMEM;
142         }
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;
148
149         init_completion(&req->completion);
150         err = adc_enqueue_request(client->adc, req);
151         if (err)
152         {
153                 dev_err(client->adc->dev, "fail to enqueue request\n");
154                 kfree(req);
155                 return err;
156         }
157         tmo = wait_for_completion_timeout(&req->completion,msecs_to_jiffies(100));
158         kfree(req);
159         req = NULL;
160         if(tmo == 0) {
161                 tail = (client->adc->queue_tail - 1) & (MAX_ADC_FIFO_DEPTH - 1);
162                 client->adc->queue[tail] = NULL;
163                 client->adc->queue_tail = tail;
164                 return -ETIMEDOUT;
165         }
166         return client->result;
167 }
168 EXPORT_SYMBOL(adc_sync_read);
169
170 int adc_async_read(struct adc_client *client)
171 {
172         int ret = 0;
173         struct adc_request *req = NULL;
174         
175         if(client == NULL) {
176                 printk(KERN_ERR "client point is NULL");
177                 return -EINVAL;
178         }
179         if(client->adc->is_suspended == 1) {
180                 dev_dbg(client->adc->dev, "system enter sleep\n");
181                 return -1;
182         }
183         req = kzalloc(sizeof(*req), GFP_ATOMIC);
184         if (!req) {
185                 dev_err(client->adc->dev, "no memory for adc request\n");
186                 return -ENOMEM;
187         }
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;
193
194         ret = adc_enqueue_request(client->adc, req);
195         if(ret < 0)
196                 kfree(req);
197
198         return ret;
199 }
200 EXPORT_SYMBOL(adc_async_read);
201
202 void adc_core_irq_handle(struct adc_host *adc)
203 {
204         struct adc_request *req;
205         int head, res;
206         spin_lock(&adc->lock);
207         head = adc->queue_head;
208
209         req = adc->queue[head];
210         if (WARN_ON(!req)) {
211                 spin_unlock(&adc->lock);
212                 dev_err(adc->dev, "adc irq: ADC queue empty!\n");
213                 return;
214         }
215         adc->queue[head] = NULL;
216         adc->queue_head = (head + 1) & (MAX_ADC_FIFO_DEPTH - 1);
217         
218         res = adc->ops->read(adc);
219         adc->ops->stop(adc);
220         trigger_next_adc_job_if_any(adc);
221
222         req->callback(adc->cur, req->callback_param, res);
223         if(req->status == ASYNC_READ) {
224                 kfree(req);
225                 req = NULL;
226         }
227         spin_unlock(&adc->lock);
228 }
229 EXPORT_SYMBOL(adc_core_irq_handle);
230
231