/drivers/hwmon/m_adc.c
C | 922 lines | 697 code | 168 blank | 57 comment | 86 complexity | 3aba6bbc092d018c612aff2d1daa9706 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
1/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
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 version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/mutex.h>
21#include <linux/platform_device.h>
22#include <linux/err.h>
23#include <linux/hwmon.h>
24#include <linux/hwmon-sysfs.h>
25#include <linux/miscdevice.h>
26#include <linux/fs.h>
27#include <linux/sched.h>
28#include <linux/wait.h>
29#include <linux/uaccess.h>
30#include <linux/m_adc.h>
31#include <linux/pmic8058-xoadc.h>
32#include <linux/slab.h>
33
34#define MSM_ADC_DRIVER_NAME "msm_adc"
35
36struct msm_adc_drv {
37 void *dev_h;
38 struct platform_device *pdev;
39 struct sensor_device_attribute *sens_attr;
40 struct workqueue_struct *wq;
41 struct device *hwmon;
42 struct miscdevice misc;
43 atomic_t online;
44 atomic_t total_outst;
45 wait_queue_head_t total_outst_wait;
46};
47
48/* Needed to support file_op interfaces */
49static struct msm_adc_drv *msm_adc_drv;
50
51static int conv_first_request;
52
53static ssize_t msm_adc_show_curr(struct device *dev,
54 struct device_attribute *devattr, char *buf);
55
56static int msm_adc_blocking_conversion(struct msm_adc_drv *msm_adc,
57 uint32_t chan, struct adc_chan_result *result);
58
59static int msm_adc_open(struct inode *inode, struct file *file)
60{
61 struct msm_client_data *client;
62 struct msm_adc_drv *msm_adc = msm_adc_drv;
63 struct platform_device *pdev = msm_adc->pdev;
64
65 client = kzalloc(sizeof(struct msm_client_data), GFP_KERNEL);
66 if (!client) {
67 dev_err(&pdev->dev, "Unable to allocate memory\n");
68 return -ENOMEM;
69 }
70
71 if (!try_module_get(THIS_MODULE)) {
72 kfree(client);
73 return -EACCES;
74 }
75
76 mutex_init(&client->lock);
77 INIT_LIST_HEAD(&client->complete_list);
78 init_waitqueue_head(&client->data_wait);
79 init_waitqueue_head(&client->outst_wait);
80
81 client->online = 1;
82
83 file->private_data = client;
84
85 return nonseekable_open(inode, file);
86}
87
88static int no_pending_client_requests(struct msm_client_data *client)
89{
90 mutex_lock(&client->lock);
91
92 if (client->num_outstanding == 0) {
93 mutex_unlock(&client->lock);
94 return 1;
95 }
96
97 mutex_unlock(&client->lock);
98
99 return 0;
100}
101
102static int data_avail(struct msm_client_data *client, uint32_t *pending)
103{
104 uint32_t completed;
105
106 mutex_lock(&client->lock);
107 completed = client->num_complete;
108 mutex_unlock(&client->lock);
109
110 if (completed > 0) {
111 if (pending != NULL)
112 *pending = completed;
113 return 1;
114 }
115
116 return 0;
117}
118
119static int msm_adc_release(struct inode *inode, struct file *file)
120{
121 struct msm_client_data *client = file->private_data;
122 struct adc_conv_slot *slot, *tmp;
123 int rc;
124 struct msm_adc_platform_data *pdata =
125 msm_adc_drv->pdev->dev.platform_data;
126 struct msm_adc_channels *channel = pdata->channel;
127
128 module_put(THIS_MODULE);
129
130 mutex_lock(&client->lock);
131
132 /* prevent any further requests while we teardown the client */
133 client->online = 0;
134
135 mutex_unlock(&client->lock);
136
137 /*
138 * We may still have outstanding transactions in flight from this
139 * client that have not completed. Make sure they're completed
140 * before removing the client.
141 */
142 rc = wait_event_interruptible(client->outst_wait,
143 no_pending_client_requests(client));
144 if (rc) {
145 pr_err("%s: wait_event_interruptible failed rc = %d\n",
146 __func__, rc);
147 return rc;
148 }
149
150 /*
151 * All transactions have completed. Add slot resources back to the
152 * appropriate devices.
153 */
154 list_for_each_entry_safe(slot, tmp, &client->complete_list, list) {
155 slot->client = NULL;
156 list_del(&slot->list);
157 channel[slot->conv.result.chan].adc_access_fn->adc_restore_slot(
158 channel[slot->conv.result.chan].adc_dev_instance, slot);
159 }
160
161 kfree(client);
162
163 return 0;
164}
165
166static int msm_adc_lookup(struct msm_adc_drv *msm_adc,
167 struct msm_adc_lookup *lookup)
168{
169 struct platform_device *pdev = msm_adc->pdev;
170 struct msm_adc_platform_data *pdata = msm_adc->pdev->dev.platform_data;
171 int rc = 0, i = 0;
172
173 do {
174 if (strcmp(lookup->name, pdata->channel[i].name))
175 i++;
176 else
177 break;
178 } while (i < pdata->num_chan_supported);
179
180 if (i == pdata->num_chan_supported)
181 rc = -EINVAL;
182
183 if (rc) {
184 dev_err(&pdev->dev, "Lookup failed for %s\n", lookup->name);
185 return rc;
186 }
187
188 lookup->chan_idx = i;
189 return rc;
190}
191
192static int msm_adc_aio_conversion(struct msm_adc_drv *msm_adc,
193 struct adc_chan_result *request,
194 struct msm_client_data *client)
195{
196 struct msm_adc_platform_data *pdata =
197 msm_adc_drv->pdev->dev.platform_data;
198 struct msm_adc_channels *channel = &pdata->channel[request->chan];
199 struct adc_conv_slot *slot;
200
201 /* we could block here, but only for a bounded time */
202 channel->adc_access_fn->adc_slot_request(channel->adc_dev_instance,
203 &slot);
204
205 if (slot) {
206 atomic_inc(&msm_adc->total_outst);
207 mutex_lock(&client->lock);
208 client->num_outstanding++;
209 mutex_unlock(&client->lock);
210
211 /* indicates non blocking request to callback handler */
212 slot->blocking = 0;
213 slot->compk = NULL;/*For kernel space usage; n/a for usr space*/
214 slot->conv.result.chan = client->adc_chan = request->chan;
215 slot->client = client;
216 slot->adc_request = START_OF_CONV;
217 slot->chan_path = channel->chan_path_type;
218 slot->chan_adc_config = channel->adc_config_type;
219 slot->chan_adc_calib = channel->adc_calib_type;
220 queue_work(msm_adc->wq, &slot->work);
221 return 0;
222 }
223 return -EBUSY;
224}
225
226static int msm_adc_poll_complete(struct msm_adc_drv *msm_adc,
227 struct msm_client_data *client, uint32_t *pending)
228{
229 int rc;
230
231 /*
232 * Don't proceed if there there's nothing queued on this client.
233 * We could deadlock otherwise in a single threaded scenario.
234 */
235 if (no_pending_client_requests(client))
236 return -EDEADLK;
237
238 rc = wait_event_interruptible(client->data_wait,
239 data_avail(client, pending));
240 if (rc)
241 return rc;
242
243 return 0;
244}
245
246static int msm_adc_read_result(struct msm_adc_drv *msm_adc,
247 struct msm_client_data *client,
248 struct adc_chan_result *result)
249{
250 struct msm_adc_platform_data *pdata = msm_adc->pdev->dev.platform_data;
251 struct msm_adc_channels *channel = pdata->channel;
252 struct adc_conv_slot *slot;
253 int rc = 0;
254
255 mutex_lock(&client->lock);
256
257 slot = list_first_entry(&client->complete_list,
258 struct adc_conv_slot, list);
259 if (!slot) {
260 mutex_unlock(&client->lock);
261 return -ENOMSG;
262 }
263
264 slot->client = NULL;
265 list_del(&slot->list);
266
267 client->num_complete--;
268
269 mutex_unlock(&client->lock);
270
271 *result = slot->conv.result;
272
273 /* restore this slot to reserve */
274 channel[slot->conv.result.chan].adc_access_fn->adc_restore_slot(
275 channel[slot->conv.result.chan].adc_dev_instance, slot);
276
277 return rc;
278}
279
280static long msm_adc_ioctl(struct file *file, unsigned int cmd,
281 unsigned long arg)
282{
283 struct msm_client_data *client = file->private_data;
284 struct msm_adc_drv *msm_adc = msm_adc_drv;
285 struct platform_device *pdev = msm_adc->pdev;
286 int rc;
287
288 switch (cmd) {
289 case MSM_ADC_REQUEST:
290 {
291 struct adc_chan_result conv;
292
293 if (copy_from_user(&conv, (void __user *)arg,
294 sizeof(struct adc_chan_result)))
295 return -EFAULT;
296
297 rc = msm_adc_blocking_conversion(msm_adc, conv.chan,
298 &conv);
299 if (rc) {
300 dev_dbg(&pdev->dev, "BLK conversion failed\n");
301 return rc;
302 }
303
304 if (copy_to_user((void __user *)arg, &conv,
305 sizeof(struct adc_chan_result)))
306 return -EFAULT;
307 break;
308 }
309 case MSM_ADC_AIO_REQUEST:
310 {
311 struct adc_chan_result conv;
312
313 if (copy_from_user(&conv, (void __user *)arg,
314 sizeof(struct adc_chan_result)))
315 return -EFAULT;
316
317 rc = msm_adc_aio_conversion(msm_adc, &conv, client);
318 if (rc) {
319 dev_dbg(&pdev->dev, "AIO conversion failed\n");
320 return rc;
321 }
322 break;
323 }
324 case MSM_ADC_AIO_POLL:
325 {
326 uint32_t completed;
327
328 rc = msm_adc_poll_complete(msm_adc, client, &completed);
329 if (rc) {
330 dev_dbg(&pdev->dev, "poll request failed\n");
331 return rc;
332 }
333
334 if (copy_to_user((void __user *)arg, &completed,
335 sizeof(uint32_t)))
336 return -EFAULT;
337
338 break;
339 }
340 case MSM_ADC_AIO_READ:
341 {
342 struct adc_chan_result result;
343
344 rc = msm_adc_read_result(msm_adc, client, &result);
345 if (rc) {
346 dev_dbg(&pdev->dev, "read result failed\n");
347 return rc;
348 }
349
350 if (copy_to_user((void __user *)arg, &result,
351 sizeof(struct adc_chan_result)))
352 return -EFAULT;
353 break;
354 }
355 case MSM_ADC_LOOKUP:
356 {
357 struct msm_adc_lookup lookup;
358
359 if (copy_from_user(&lookup, (void __user *)arg,
360 sizeof(struct msm_adc_lookup)))
361 return -EFAULT;
362
363 rc = msm_adc_lookup(msm_adc, &lookup);
364 if (rc) {
365 dev_dbg(&pdev->dev, "No such channel: %s\n",
366 lookup.name);
367 return rc;
368 }
369
370 if (copy_to_user((void __user *)arg, &lookup,
371 sizeof(struct msm_adc_lookup)))
372 return -EFAULT;
373 break;
374 }
375 default:
376 return -EINVAL;
377 }
378
379 return 0;
380}
381
382const struct file_operations msm_adc_fops = {
383 .open = msm_adc_open,
384 .release = msm_adc_release,
385 .unlocked_ioctl = msm_adc_ioctl,
386};
387
388static ssize_t msm_adc_show_curr(struct device *dev,
389 struct device_attribute *devattr, char *buf)
390{
391 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
392 struct msm_adc_drv *msm_adc = dev_get_drvdata(dev);
393 int rc;
394 struct adc_chan_result result;
395
396 rc = pm8058_xoadc_registered();
397 if (rc <= 0)
398 return -ENODEV;
399
400 rc = msm_adc_blocking_conversion(msm_adc, attr->index, &result);
401 if (rc)
402 return 0;
403
404 return sprintf(buf, "Result: %lld Raw: %d\n", result.physical,
405 result.adc_code);
406}
407
408static int msm_adc_blocking_conversion(struct msm_adc_drv *msm_adc,
409 uint32_t hwmon_chan, struct adc_chan_result *result)
410{
411 struct adc_conv_slot *slot;
412 struct msm_adc_platform_data *pdata =
413 msm_adc_drv->pdev->dev.platform_data;
414 struct msm_adc_channels *channel = &pdata->channel[hwmon_chan];
415 int ret;
416
417 if (!conv_first_request) {
418 ret = pm8058_xoadc_calib_device(channel->adc_dev_instance);
419 if (ret) {
420 pr_err("pmic8058 xoadc calibration failed, retry\n");
421 return ret;
422 }
423 conv_first_request = 1;
424 }
425
426 channel->adc_access_fn->adc_slot_request(channel->adc_dev_instance,
427 &slot);
428 if (slot) {
429 slot->conv.result.chan = hwmon_chan;
430 /* indicates blocking request to callback handler */
431 slot->blocking = 1;
432 slot->adc_request = START_OF_CONV;
433 slot->chan_path = channel->chan_path_type;
434 slot->chan_adc_config = channel->adc_config_type;
435 slot->chan_adc_calib = channel->adc_calib_type;
436 queue_work(msm_adc_drv->wq, &slot->work);
437
438 wait_for_completion_interruptible(&slot->comp);
439 *result = slot->conv.result;
440 channel->adc_access_fn->adc_restore_slot(
441 channel->adc_dev_instance, slot);
442 return 0;
443 }
444 return -EBUSY;
445}
446
447void msm_adc_conv_cb(void *context, u32 param,
448 void *evt_buf, u32 len)
449{
450 struct adc_conv_slot *slot = context;
451 struct msm_adc_drv *msm_adc = msm_adc_drv;
452
453 switch (slot->adc_request) {
454 case START_OF_CONV:
455 slot->adc_request = END_OF_CONV;
456 break;
457 case START_OF_CALIBRATION:
458 slot->adc_request = END_OF_CALIBRATION;
459 break;
460 case END_OF_CALIBRATION:
461 case END_OF_CONV:
462 break;
463 }
464 queue_work(msm_adc->wq, &slot->work);
465}
466EXPORT_SYMBOL(msm_adc_conv_cb);
467
468static void msm_adc_teardown_device(struct platform_device *pdev,
469 struct msm_adc_drv *msm_adc)
470{
471 struct msm_adc_platform_data *pdata = pdev->dev.platform_data;
472 int i, num_chans = pdata->num_chan_supported;
473
474 if (msm_adc->sens_attr)
475 for (i = 0; i < num_chans; i++)
476 device_remove_file(&pdev->dev,
477 &msm_adc->sens_attr[i].dev_attr);
478
479 kfree(msm_adc->sens_attr);
480}
481
482static void msm_adc_teardown(struct platform_device *pdev)
483{
484 struct msm_adc_drv *msm_adc = platform_get_drvdata(pdev);
485
486 if (!msm_adc)
487 return;
488
489 misc_deregister(&msm_adc->misc);
490
491 if (msm_adc->hwmon)
492 hwmon_device_unregister(msm_adc->hwmon);
493
494 msm_adc_teardown_device(pdev, msm_adc);
495
496 if (msm_adc->dev_h)
497 msm_adc->dev_h = NULL;
498
499 kfree(msm_adc);
500 platform_set_drvdata(pdev, NULL);
501}
502
503/*
504 * Process the deferred job
505 */
506void msm_adc_wq_work(struct work_struct *work)
507{
508 struct adc_properties *adc_properties;
509 struct adc_conv_slot *slot = container_of(work,
510 struct adc_conv_slot, work);
511 uint32_t idx = slot->conv.result.chan;
512 struct msm_adc_platform_data *pdata =
513 msm_adc_drv->pdev->dev.platform_data;
514 struct msm_adc_channels *channel = &pdata->channel[idx];
515 int32_t adc_code;
516
517 switch (slot->adc_request) {
518 case START_OF_CONV:
519 channel->adc_access_fn->adc_select_chan_and_start_conv(
520 channel->adc_dev_instance, slot);
521 break;
522 case END_OF_CONV:
523 adc_properties = channel->adc_access_fn->adc_get_properties(
524 channel->adc_dev_instance);
525 if (channel->adc_access_fn->adc_read_adc_code)
526 channel->adc_access_fn->adc_read_adc_code(
527 channel->adc_dev_instance, &adc_code);
528 if (channel->chan_processor)
529 channel->chan_processor(adc_code, adc_properties,
530 &slot->chan_properties, &slot->conv.result);
531 /* Intentionally a fall thru here. Calibraton does not need
532 to perform channel processing, etc. However, both
533 end of conversion and end of calibration requires the below
534 fall thru code to be executed. */
535 case END_OF_CALIBRATION:
536 /* for blocking requests, signal complete */
537 if (slot->blocking)
538 complete(&slot->comp);
539 else {
540 struct msm_client_data *client = slot->client;
541
542 mutex_lock(&client->lock);
543
544 if (slot->adc_request == END_OF_CONV) {
545 list_add(&slot->list, &client->complete_list);
546 client->num_complete++;
547 }
548 client->num_outstanding--;
549
550 /*
551 * if the client release has been invoked and this is call
552 * corresponds to the last request, then signal release
553 * to complete.
554 */
555 if (slot->client->online == 0 &&
556 client->num_outstanding == 0)
557 wake_up_interruptible_all(&client->outst_wait);
558
559 mutex_unlock(&client->lock);
560
561 wake_up_interruptible_all(&client->data_wait);
562
563 atomic_dec(&msm_adc_drv->total_outst);
564
565 /* verify driver remove has not been invoked */
566 if (atomic_read(&msm_adc_drv->online) == 0 &&
567 atomic_read(&msm_adc_drv->total_outst) == 0)
568 wake_up_interruptible_all(
569 &msm_adc_drv->total_outst_wait);
570
571 if (slot->compk) /* Kernel space request */
572 complete(slot->compk);
573 if (slot->adc_request == END_OF_CALIBRATION)
574 channel->adc_access_fn->adc_restore_slot(
575 channel->adc_dev_instance, slot);
576 }
577 break;
578 case START_OF_CALIBRATION: /* code here to please code reviewers
579 to satisfy silly compiler warnings */
580 break;
581 }
582}
583EXPORT_SYMBOL(msm_adc_wq_work);
584
585static struct sensor_device_attribute msm_adc_curr_in_attr =
586 SENSOR_ATTR(NULL, S_IRUGO, msm_adc_show_curr, NULL, 0);
587
588static int __devinit msm_adc_init_hwmon(struct platform_device *pdev,
589 struct msm_adc_drv *msm_adc)
590{
591 struct msm_adc_platform_data *pdata = pdev->dev.platform_data;
592 struct msm_adc_channels *channel = pdata->channel;
593 int i, rc, num_chans = pdata->num_chan_supported;
594
595 if (!channel)
596 return -EINVAL;
597
598 msm_adc->sens_attr = kzalloc(num_chans *
599 sizeof(struct sensor_device_attribute), GFP_KERNEL);
600 if (!msm_adc->sens_attr) {
601 dev_err(&pdev->dev, "Unable to allocate memory\n");
602 rc = -ENOMEM;
603 goto hwmon_err_sens;
604 }
605
606 for (i = 0; i < num_chans; i++) {
607 msm_adc_curr_in_attr.index = i;
608 msm_adc_curr_in_attr.dev_attr.attr.name = channel[i].name;
609 memcpy(&msm_adc->sens_attr[i], &msm_adc_curr_in_attr,
610 sizeof(msm_adc_curr_in_attr));
611
612 rc = device_create_file(&pdev->dev,
613 &msm_adc->sens_attr[i].dev_attr);
614 if (rc) {
615 dev_err(&pdev->dev, "device_create_file failed for "
616 "dal dev %s\n",
617 channel[i].name);
618 goto hwmon_err_sens;
619 }
620 }
621
622 return 0;
623
624hwmon_err_sens:
625 kfree(msm_adc->sens_attr);
626
627 return rc;
628}
629
630static int __devinit msm_adc_probe(struct platform_device *pdev)
631{
632 struct msm_adc_platform_data *pdata = pdev->dev.platform_data;
633 struct msm_adc_drv *msm_adc;
634 int rc = 0;
635
636 if (!pdata) {
637 dev_err(&pdev->dev, "no platform data?\n");
638 return -EINVAL;
639 }
640
641 msm_adc = kzalloc(sizeof(struct msm_adc_drv), GFP_KERNEL);
642 if (!msm_adc) {
643 dev_err(&pdev->dev, "Unable to allocate memory\n");
644 return -ENOMEM;
645 }
646
647 platform_set_drvdata(pdev, msm_adc);
648 msm_adc_drv = msm_adc;
649 msm_adc->pdev = pdev;
650
651 rc = msm_adc_init_hwmon(pdev, msm_adc);
652 if (rc) {
653 dev_err(&pdev->dev, "msm_adc_dev_init failed\n");
654 goto err_cleanup;
655 }
656
657 msm_adc->hwmon = hwmon_device_register(&pdev->dev);
658 if (IS_ERR(msm_adc->hwmon)) {
659 dev_err(&pdev->dev, "hwmon_device_register failed.\n");
660 rc = PTR_ERR(msm_adc->hwmon);
661 goto err_cleanup;
662 }
663
664 msm_adc->misc.name = MSM_ADC_DRIVER_NAME;
665 msm_adc->misc.minor = MISC_DYNAMIC_MINOR;
666 msm_adc->misc.fops = &msm_adc_fops;
667
668 if (misc_register(&msm_adc->misc)) {
669 dev_err(&pdev->dev, "Unable to register misc device!\n");
670 goto err_cleanup;
671 }
672
673 init_waitqueue_head(&msm_adc->total_outst_wait);
674 atomic_set(&msm_adc->online, 1);
675 atomic_set(&msm_adc->total_outst, 0);
676
677 msm_adc->wq = create_singlethread_workqueue("msm_adc");
678 if (!msm_adc->wq)
679 goto err_cleanup;
680
681 pr_info("msm_adc successfully registered\n");
682
683 return 0;
684
685err_cleanup:
686 msm_adc_teardown(pdev);
687
688 return rc;
689}
690
691static int __devexit msm_adc_remove(struct platform_device *pdev)
692{
693 int rc;
694
695 struct msm_adc_drv *msm_adc = platform_get_drvdata(pdev);
696
697 atomic_set(&msm_adc->online, 0);
698
699 misc_deregister(&msm_adc->misc);
700
701 hwmon_device_unregister(msm_adc->hwmon);
702 msm_adc->hwmon = NULL;
703
704 /*
705 * We may still have outstanding transactions in flight that have not
706 * completed. Make sure they're completed before tearing down.
707 */
708 rc = wait_event_interruptible(msm_adc->total_outst_wait,
709 atomic_read(&msm_adc->total_outst) == 0);
710 if (rc) {
711 pr_err("%s: wait_event_interruptible failed rc = %d\n",
712 __func__, rc);
713 return rc;
714 }
715
716 msm_adc_teardown(pdev);
717
718 pr_info("msm_adc unregistered\n");
719
720 return 0;
721}
722
723static struct platform_driver msm_adc_driver = {
724 .probe = msm_adc_probe,
725 .remove = __devexit_p(msm_adc_remove),
726 .driver = {
727 .name = MSM_ADC_DRIVER_NAME,
728 .owner = THIS_MODULE,
729 },
730};
731
732static int __init msm_adc_init(void)
733{
734 return platform_driver_register(&msm_adc_driver);
735}
736module_init(msm_adc_init);
737
738static void __exit msm_adc_exit(void)
739{
740 platform_driver_unregister(&msm_adc_driver);
741}
742module_exit(msm_adc_exit);
743
744MODULE_DESCRIPTION("MSM ADC Driver");
745MODULE_ALIAS("platform:msm_adc");
746MODULE_LICENSE("GPL v2");
747MODULE_VERSION("0.1");
748
749
750int32_t adc_channel_open(uint32_t channel, void **h)
751{
752 struct msm_client_data *client;
753 struct msm_adc_drv *msm_adc = msm_adc_drv;
754 struct msm_adc_platform_data *pdata;
755 struct platform_device *pdev;
756 int i = 0, rc;
757
758 if (!msm_adc_drv)
759 return -EFAULT;
760
761 rc = pm8058_xoadc_registered();
762
763 if (rc <= 0)
764 return -ENODEV;
765
766 pdata = msm_adc->pdev->dev.platform_data;
767 pdev = msm_adc->pdev;
768
769 while (i < pdata->num_chan_supported) {
770 if (channel == pdata->channel[i].channel_name)
771 break;
772 else
773 i++;
774 }
775
776 if (i == pdata->num_chan_supported)
777 return -EBADF; /* unknown channel */
778
779 client = kzalloc(sizeof(struct msm_client_data), GFP_KERNEL);
780 if (!client) {
781 dev_err(&pdev->dev, "Unable to allocate memory\n");
782 return -ENOMEM;
783 }
784
785 if (!try_module_get(THIS_MODULE)) {
786 kfree(client);
787 return -EACCES;
788 }
789
790 mutex_init(&client->lock);
791 INIT_LIST_HEAD(&client->complete_list);
792 init_waitqueue_head(&client->data_wait);
793 init_waitqueue_head(&client->outst_wait);
794
795 client->online = 1;
796 client->adc_chan = i;
797 *h = (void *)client;
798 return 0;
799}
800
801int32_t adc_channel_close(void *h)
802{
803 struct msm_client_data *client = (struct msm_client_data *)h;
804
805 kfree(client);
806 return 0;
807}
808
809int32_t adc_channel_request_conv(void *h, struct completion *conv_complete_evt)
810{
811 struct msm_client_data *client = (struct msm_client_data *)h;
812 struct msm_adc_platform_data *pdata =
813 msm_adc_drv->pdev->dev.platform_data;
814 struct msm_adc_channels *channel = &pdata->channel[client->adc_chan];
815 struct adc_conv_slot *slot;
816 int ret;
817
818 if (!conv_first_request) {
819 ret = pm8058_xoadc_calib_device(channel->adc_dev_instance);
820 if (ret) {
821 pr_err("pm8058 xoadc calibration failed, retry\n");
822 return ret;
823 }
824 conv_first_request = 1;
825 }
826
827 channel->adc_access_fn->adc_slot_request(channel->adc_dev_instance,
828 &slot);
829
830 if (slot) {
831 atomic_inc(&msm_adc_drv->total_outst);
832 mutex_lock(&client->lock);
833 client->num_outstanding++;
834 mutex_unlock(&client->lock);
835
836 slot->conv.result.chan = client->adc_chan;
837 slot->blocking = 0;
838 slot->compk = conv_complete_evt;
839 slot->client = client;
840 slot->adc_request = START_OF_CONV;
841 slot->chan_path = channel->chan_path_type;
842 slot->chan_adc_config = channel->adc_config_type;
843 slot->chan_adc_calib = channel->adc_calib_type;
844 queue_work(msm_adc_drv->wq, &slot->work);
845 return 0;
846 }
847 return -EBUSY;
848}
849
850int32_t adc_channel_read_result(void *h, struct adc_chan_result *chan_result)
851{
852 struct msm_client_data *client = (struct msm_client_data *)h;
853 struct msm_adc_platform_data *pdata =
854 msm_adc_drv->pdev->dev.platform_data;
855 struct msm_adc_channels *channel = pdata->channel;
856 struct adc_conv_slot *slot;
857 int rc = 0;
858
859 mutex_lock(&client->lock);
860
861 slot = list_first_entry(&client->complete_list,
862 struct adc_conv_slot, list);
863 if (!slot) {
864 mutex_unlock(&client->lock);
865 return -ENOMSG;
866 }
867
868 slot->client = NULL;
869 list_del(&slot->list);
870
871 client->num_complete--;
872
873 mutex_unlock(&client->lock);
874
875 *chan_result = slot->conv.result;
876
877 /* restore this slot to reserve */
878 channel[slot->conv.result.chan].adc_access_fn->adc_restore_slot(
879 channel[slot->conv.result.chan].adc_dev_instance, slot);
880
881 return rc;
882}
883
884int32_t adc_calib_request(void *h, struct completion *calib_complete_evt)
885{
886 struct msm_client_data *client = (struct msm_client_data *)h;
887 struct msm_adc_platform_data *pdata =
888 msm_adc_drv->pdev->dev.platform_data;
889 struct msm_adc_channels *channel = &pdata->channel[client->adc_chan];
890 struct adc_conv_slot *slot;
891 int rc, calib_status;
892
893 channel->adc_access_fn->adc_slot_request(channel->adc_dev_instance,
894 &slot);
895 if (slot) {
896 slot->conv.result.chan = client->adc_chan;
897 slot->blocking = 0;
898 slot->compk = calib_complete_evt;
899 slot->adc_request = START_OF_CALIBRATION;
900 slot->chan_path = channel->chan_path_type;
901 slot->chan_adc_config = channel->adc_config_type;
902 slot->chan_adc_calib = channel->adc_calib_type;
903 rc = channel->adc_access_fn->adc_calibrate(
904 channel->adc_dev_instance, slot, &calib_status);
905
906 if (calib_status == CALIB_NOT_REQUIRED) {
907 channel->adc_access_fn->adc_restore_slot(
908 channel->adc_dev_instance, slot);
909 /* client will always wait in case when
910 calibration is not required */
911 complete(calib_complete_evt);
912 } else {
913 atomic_inc(&msm_adc_drv->total_outst);
914 mutex_lock(&client->lock);
915 client->num_outstanding++;
916 mutex_unlock(&client->lock);
917 }
918
919 return rc;
920 }
921 return -EBUSY;
922}