arm64: dts: rockchip: update tsadc node for rk3368
[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 #include <linux/adc.h>
8 #include "adc_priv.h"
9
10 struct adc_host *g_adc = NULL;
11 static LIST_HEAD(adc_host_head);
12
13 struct adc_host *adc_alloc_host(struct device *dev, int extra, enum host_chn_mask mask)
14 {
15         struct adc_host *adc;
16         
17         adc = kzalloc(sizeof(struct adc_host) + extra, GFP_KERNEL);
18         if (!adc)
19                 return NULL;
20         adc->mask = mask;
21         adc->dev = dev;
22         adc->chn = -1;
23         spin_lock_init(&adc->lock);
24         mutex_init(&adc->m_lock);
25         INIT_LIST_HEAD(&adc->req_head);
26         INIT_LIST_HEAD(&adc->callback_head);
27
28         list_add_tail(&adc->entry, &adc_host_head);
29
30         return adc;
31 }
32
33 void adc_free_host(struct adc_host *adc)
34 {
35         list_del(&adc->entry);
36         kfree(adc);
37         adc = NULL;
38         return;
39 }
40
41 struct adc_client *adc_register(int chn,
42                                 void (*callback)(struct adc_client *, void *, int), 
43                                 void *callback_param)
44
45 {
46         struct adc_client *client = NULL;
47         struct adc_host *adc = NULL;
48
49         if(chn < 0)
50                 return NULL;
51         list_for_each_entry(adc, &adc_host_head, entry) {
52                 if((chn == 0 && adc->mask == SARADC_CHN_MASK) ||
53                 (chn & adc->mask)){
54                         client = kzalloc(sizeof(struct adc_client), GFP_KERNEL);
55                         if(!client)
56                                 return NULL;
57                         client->callback = callback;
58                         client->callback_param = callback_param;
59                         client->chn = chn;
60                         client->adc = adc;
61                         client->index = adc->client_count;
62                         init_waitqueue_head(&client->wait);
63                         adc->client_count++;
64
65                         return client;
66                 }
67         }
68         dev_err(adc->dev, "chn(%d) is not support\n", chn);
69         return NULL;
70 }
71 EXPORT_SYMBOL(adc_register);
72
73 void adc_unregister(struct adc_client *client)
74 {
75         struct adc_host *adc = client->adc;
76
77         adc->client_count--;
78         kfree(client);
79         client = NULL;
80         return;
81 }
82 EXPORT_SYMBOL(adc_unregister);
83
84 static inline void trigger_next_adc_job_if_any(struct adc_host *adc)
85 {
86         struct adc_request *req = NULL;
87
88         req = list_first_entry(&adc->req_head, struct adc_request, entry);
89         if(req){
90                 if(req->client == NULL){
91                         dev_err(adc->dev, "Abnormal: client piont is NULL...............\n");
92                         return;
93                 }
94                 adc->chn = req->client->chn;
95                 adc->ops->start(adc);
96         }
97
98         return;
99 }
100
101 static int adc_request_add(struct adc_host *adc, struct adc_client *client)
102 {
103         struct adc_request *req = NULL;
104
105         req = kzalloc(sizeof(struct adc_request), GFP_ATOMIC);
106
107         if(unlikely(!req))
108                 return -ENOMEM;
109         INIT_LIST_HEAD(&req->entry);
110         req->client = client;
111         list_add_tail(&req->entry, &adc->req_head);
112         if(adc->chn == -1)
113                 trigger_next_adc_job_if_any(adc);
114         return 0;
115 }
116 static void
117 adc_sync_read_callback(struct adc_client *client, void *param, int result)
118 {
119         client->result = result;
120 }
121
122 static void adc_callback(struct adc_host *adc)
123 {
124         struct adc_request *req = NULL, *n = NULL;
125
126         list_for_each_entry_safe(req, n, &adc->callback_head, entry) {
127                 if(req->client->flags & (1<<ADC_ASYNC_READ)){
128                         req->client->callback(req->client, req->client->callback_param, req->client->result);
129                 }
130                 if(req->client->flags & (1<<ADC_SYNC_READ)){
131                         adc_sync_read_callback(req->client, NULL, req->client->result);
132                         req->client->is_finished = 1;
133                         wake_up(&req->client->wait);
134                 }
135                 req->client->flags = 0;
136                 list_del_init(&req->entry);
137                 kfree(req);
138         }
139 }
140
141 void adc_finished(struct adc_host *adc, int result)
142 {
143         unsigned long flags;
144         struct adc_request *req = NULL, *n = NULL;
145
146         adc->ops->stop(adc);
147         udelay(SAMPLE_RATE);
148         spin_lock_irqsave(&adc->lock, flags);
149         list_for_each_entry_safe(req, n, &adc->req_head, entry) {
150                 if(req->client->chn == adc->chn){
151                         req->client->result = result;
152                         list_move_tail(&req->entry, &adc->callback_head);
153                 }
154         }
155         adc->chn = -1;
156         if(!list_empty(&adc->req_head))
157                 trigger_next_adc_job_if_any(adc);
158         spin_unlock_irqrestore(&adc->lock, flags);
159
160         adc_callback(adc);
161 }
162
163 void adc_core_irq_handle(struct adc_host *adc)
164 {
165         int result = 0;
166
167         WARN_ON(adc->chn == -1);
168
169         mutex_lock(&adc->m_lock);
170
171         result = adc->ops->read(adc);
172         adc_dbg(adc->dev, "chn[%d] read value: %d\n", adc->chn, result);
173
174         adc_finished(adc, result);
175
176         mutex_unlock(&adc->m_lock);
177 }
178
179 int adc_host_read(struct adc_client *client, enum read_type type)
180 {
181         int tmo, ret = 0;
182         unsigned long flags;
183         struct adc_host *adc = NULL;
184
185         if(client == NULL) {
186                 printk(KERN_ERR "client is NULL");
187                 return -EINVAL;
188         }
189         adc = client->adc;
190         if(adc->is_suspended == 1) {
191                 dev_err(adc->dev, "adc is in suspend state\n");
192                 return -EIO;
193         }
194
195         spin_lock_irqsave(&adc->lock, flags);
196         if(client->flags & (1<<type)){
197                 spin_unlock_irqrestore(&adc->lock, flags);
198                 adc_dbg(adc->dev, "req is exist: %s, client->index: %d\n", 
199                                 (type == ADC_ASYNC_READ)?"async_read":"sync_read", client->index);
200                 return -EEXIST;
201         }else if(client->flags != 0){
202                 client->flags |= 1<<type;
203         }else{
204                 client->flags = 1<<type;
205                 ret = adc_request_add(adc, client);
206                 if(ret < 0){
207                         spin_unlock_irqrestore(&adc->lock, flags);
208                         dev_err(adc->dev, "fail to add request\n");
209                         return ret;
210                 }
211         }
212         if(type == ADC_ASYNC_READ){
213                 spin_unlock_irqrestore(&adc->lock, flags);
214                 return 0;
215         }
216         client->is_finished = 0;
217         spin_unlock_irqrestore(&adc->lock, flags);
218
219         tmo = wait_event_timeout(client->wait, ( client->is_finished == 1 ), msecs_to_jiffies(ADC_READ_TMO));
220         mutex_lock(&adc->m_lock);
221         if(unlikely((tmo <= 0) && (client->is_finished == 0))) {
222                 dev_err(adc->dev, "get adc value timeout.................................\n");
223                 if(adc->ops->dump)
224                         adc->ops->dump(adc);
225                 adc_finished(adc, -1);
226                 mutex_unlock(&adc->m_lock);
227                 return -ETIMEDOUT;
228         } 
229         mutex_unlock(&adc->m_lock);
230
231         return client->result;
232 }
233
234 int adc_sync_read(struct adc_client *client)
235 {
236         return adc_host_read(client, ADC_SYNC_READ);
237 }
238 EXPORT_SYMBOL(adc_sync_read);
239
240 int adc_async_read(struct adc_client *client)
241 {
242         return adc_host_read(client, ADC_ASYNC_READ);
243 }
244
245 EXPORT_SYMBOL(adc_async_read);
246
247 int adc_get_def_ref_volt(void)
248 {
249         return g_adc->pdata->ref_volt;
250 }
251 EXPORT_SYMBOL(adc_get_def_ref_volt);
252
253 int adc_get_curr_ref_volt(void)
254 {
255         int v = 0, volt = 0;
256
257         if(!g_adc)
258                 return -EINVAL;
259         if(!g_adc->base_client)
260                 return g_adc->pdata->ref_volt;
261
262         volt = g_adc->pdata->get_base_volt();
263         if(volt < 0)
264                 return g_adc->pdata->ref_volt;
265         
266         v = adc_sync_read(g_adc->base_client);
267         if(v < 0)
268                 return v;
269
270         return volt * 1024 / v;
271 }
272 EXPORT_SYMBOL(adc_get_curr_ref_volt);