blob: e4a607fc1abedf752dc2b641e5af58a4708b4638 [file] [log] [blame]
Stephen Boyd3c9bd8f2012-02-21 23:49:06 -08001/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
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
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/mutex.h>
16#include <linux/platform_device.h>
17#include <linux/err.h>
18#include <linux/hwmon.h>
19#include <linux/hwmon-sysfs.h>
20#include <linux/miscdevice.h>
21#include <linux/fs.h>
22#include <linux/sched.h>
23#include <linux/wait.h>
24#include <linux/uaccess.h>
25#include <linux/msm_adc.h>
26#include <linux/pmic8058-xoadc.h>
27#include <linux/slab.h>
28#include <linux/semaphore.h>
29
30#include <mach/dal.h>
31
32#define MSM_ADC_DRIVER_NAME "msm_adc"
33#define MSM_ADC_MAX_FNAME 15
34
35#define MSM_ADC_DALRPC_DEVICEID 0x02000067
36#define MSM_ADC_DALRPC_PORT_NAME "DAL00"
37#define MSM_ADC_DALRPC_CPU SMD_APPS_MODEM
38
39#define MSM_ADC_DALRPC_CMD_REQ_CONV 9
40#define MSM_ADC_DALRPC_CMD_INPUT_PROP 11
41
42#define MSM_ADC_DALRC_CONV_TIMEOUT (5 * HZ) /* 5 seconds */
43
Siddartha Mohanadossbc2103f2012-03-20 11:41:48 -070044#define MSM_8x25_ADC_DEV_ID 0
45#define MSM_8x25_CHAN_ID 16
46
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070047enum dal_error {
48 DAL_ERROR_INVALID_DEVICE_IDX = 1,
49 DAL_ERROR_INVALID_CHANNEL_IDX,
50 DAL_ERROR_NULL_POINTER,
51 DAL_ERROR_DEVICE_QUEUE_FULL,
52 DAL_ERROR_INVALID_PROPERTY_LENGTH,
53 DAL_ERROR_REMOTE_EVENT_POOL_FULL
54};
55
56enum dal_result_status {
57 DAL_RESULT_STATUS_INVALID,
58 DAL_RESULT_STATUS_VALID
59};
60
61struct dal_conv_state {
62 struct dal_conv_slot context[MSM_ADC_DEV_MAX_INFLIGHT];
63 struct list_head slots;
64 struct mutex list_lock;
65 struct semaphore slot_count;
66};
67
68struct adc_dev {
69 char *name;
70 uint32_t nchans;
71 struct dal_conv_state conv;
72 struct dal_translation transl;
73 struct sensor_device_attribute *sens_attr;
74 char **fnames;
75};
76
77struct msm_adc_drv {
78 /* Common to both XOADC and EPM */
79 struct platform_device *pdev;
80 struct device *hwmon;
81 struct miscdevice misc;
82 /* XOADC variables */
83 struct sensor_device_attribute *sens_attr;
84 struct workqueue_struct *wq;
85 atomic_t online;
86 atomic_t total_outst;
87 wait_queue_head_t total_outst_wait;
88
89 /* EPM variables */
90 void *dev_h;
91 struct adc_dev *devs[MSM_ADC_MAX_NUM_DEVS];
92 struct mutex prop_lock;
93 atomic_t rpc_online;
94 atomic_t rpc_total_outst;
95 wait_queue_head_t rpc_total_outst_wait;
96};
97
98static bool epm_init;
99static bool epm_fluid_enabled;
100
101/* Needed to support file_op interfaces */
102static struct msm_adc_drv *msm_adc_drv;
103
Vijayakumar Muthuvel Manickam2d2a2c52011-10-20 13:41:39 -0700104static bool conv_first_request;
105
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700106static ssize_t msm_adc_show_curr(struct device *dev,
107 struct device_attribute *devattr, char *buf);
108
109static int msm_rpc_adc_blocking_conversion(struct msm_adc_drv *msm_adc,
110 uint32_t chan, struct adc_chan_result *result);
111
112static int msm_adc_blocking_conversion(struct msm_adc_drv *msm_adc,
113 uint32_t chan, struct adc_chan_result *result);
114
115static int msm_adc_open(struct inode *inode, struct file *file)
116{
117 struct msm_client_data *client;
118 struct msm_adc_drv *msm_adc = msm_adc_drv;
119 struct platform_device *pdev = msm_adc->pdev;
120
121 client = kzalloc(sizeof(struct msm_client_data), GFP_KERNEL);
122 if (!client) {
123 dev_err(&pdev->dev, "Unable to allocate memory\n");
124 return -ENOMEM;
125 }
126
127 if (!try_module_get(THIS_MODULE)) {
128 kfree(client);
129 return -EACCES;
130 }
131
132 mutex_init(&client->lock);
133 INIT_LIST_HEAD(&client->complete_list);
134 init_waitqueue_head(&client->data_wait);
135 init_waitqueue_head(&client->outst_wait);
136
137 client->online = 1;
138
139 file->private_data = client;
140
141 return nonseekable_open(inode, file);
142}
143
144static inline void msm_adc_restore_slot(struct dal_conv_state *conv_s,
145 struct dal_conv_slot *slot)
146{
147 mutex_lock(&conv_s->list_lock);
148 list_add(&slot->list, &conv_s->slots);
149 mutex_unlock(&conv_s->list_lock);
150
151 up(&conv_s->slot_count);
152}
153
154static int no_pending_client_requests(struct msm_client_data *client)
155{
156 mutex_lock(&client->lock);
157
158 if (client->num_outstanding == 0) {
159 mutex_unlock(&client->lock);
160 return 1;
161 }
162
163 mutex_unlock(&client->lock);
164
165 return 0;
166}
167
168static int data_avail(struct msm_client_data *client, uint32_t *pending)
169{
170 uint32_t completed;
171
172 mutex_lock(&client->lock);
173 completed = client->num_complete;
174 mutex_unlock(&client->lock);
175
176 if (completed > 0) {
177 if (pending != NULL)
178 *pending = completed;
179 return 1;
180 }
181
182 return 0;
183}
184
185static int msm_adc_release(struct inode *inode, struct file *file)
186{
187 struct msm_client_data *client = file->private_data;
188 struct adc_conv_slot *slot, *tmp;
189 int rc;
190 struct msm_adc_platform_data *pdata =
191 msm_adc_drv->pdev->dev.platform_data;
192 struct msm_adc_channels *channel = pdata->channel;
193
194 module_put(THIS_MODULE);
195
196 mutex_lock(&client->lock);
197
198 /* prevent any further requests while we teardown the client */
199 client->online = 0;
200
201 mutex_unlock(&client->lock);
202
203 /*
204 * We may still have outstanding transactions in flight from this
205 * client that have not completed. Make sure they're completed
206 * before removing the client.
207 */
208 rc = wait_event_interruptible(client->outst_wait,
209 no_pending_client_requests(client));
210 if (rc) {
211 pr_err("%s: wait_event_interruptible failed rc = %d\n",
212 __func__, rc);
213 return rc;
214 }
215
216 /*
217 * All transactions have completed. Add slot resources back to the
218 * appropriate devices.
219 */
220 list_for_each_entry_safe(slot, tmp, &client->complete_list, list) {
221 slot->client = NULL;
222 list_del(&slot->list);
223 channel[slot->conv.result.chan].adc_access_fn->adc_restore_slot(
224 channel[slot->conv.result.chan].adc_dev_instance, slot);
225 }
226
227 kfree(client);
228
229 return 0;
230}
231
232static int msm_adc_translate_dal_to_hwmon(struct msm_adc_drv *msm_adc,
233 uint32_t chan,
234 struct adc_dev_spec *dest)
235{
236 struct dal_translation *transl;
237 struct msm_adc_platform_data *pdata = msm_adc->pdev->dev.platform_data;
238 int i;
239
240 for (i = 0; i < pdata->num_adc; i++) {
241 transl = &msm_adc->devs[i]->transl;
242 if (chan >= transl->hwmon_start &&
243 chan <= transl->hwmon_end) {
244 dest->dal.dev_idx = transl->dal_dev_idx;
245 dest->hwmon_dev_idx = transl->hwmon_dev_idx;
246 dest->dal.chan_idx = chan - transl->hwmon_start;
247 return 0;
248 }
249 }
250 return -EINVAL;
251}
252
253static int msm_adc_translate_hwmon_to_dal(struct msm_adc_drv *msm_adc,
254 struct adc_dev_spec *source,
255 uint32_t *chan)
256{
257 struct msm_adc_platform_data *pdata = msm_adc->pdev->dev.platform_data;
258 struct dal_translation *transl;
259 int i;
260
261 for (i = 0; i < pdata->num_adc; i++) {
262 transl = &msm_adc->devs[i]->transl;
263 if (source->dal.dev_idx != transl->dal_dev_idx)
264 continue;
265 *chan = transl->hwmon_start + source->dal.chan_idx;
266 return 0;
267 }
268 return -EINVAL;
269}
270
271static int msm_adc_getinputproperties(struct msm_adc_drv *msm_adc,
272 const char *lookup_name,
273 struct adc_dev_spec *result)
274{
275 struct device *dev = &msm_adc->pdev->dev;
276 int rc;
277
278 mutex_lock(&msm_adc->prop_lock);
279
280 rc = dalrpc_fcn_8(MSM_ADC_DALRPC_CMD_INPUT_PROP, msm_adc->dev_h,
281 lookup_name, strlen(lookup_name) + 1,
282 &result->dal, sizeof(struct dal_dev_spec));
283 if (rc) {
284 dev_err(dev, "DAL getprop request failed: rc = %d\n", rc);
285 mutex_unlock(&msm_adc->prop_lock);
286 return -EIO;
287 }
288
289 mutex_unlock(&msm_adc->prop_lock);
290 return rc;
291}
292
293static int msm_adc_lookup(struct msm_adc_drv *msm_adc,
294 struct msm_adc_lookup *lookup)
295{
296 struct msm_adc_platform_data *pdata = msm_adc->pdev->dev.platform_data;
297 struct adc_dev_spec target;
298 int rc = 0, i = 0;
299 uint32_t len = 0;
300
301 len = strnlen(lookup->name, MSM_ADC_MAX_CHAN_STR);
302 while (i < pdata->num_chan_supported) {
303 if (strncmp(lookup->name, pdata->channel[i].name, len))
304 i++;
305 else
306 break;
307 }
308
309 if (pdata->num_chan_supported > 0 && i < pdata->num_chan_supported) {
310 lookup->chan_idx = i;
311 } else if (msm_adc->dev_h) {
312 rc = msm_adc_getinputproperties(msm_adc, lookup->name, &target);
313 if (rc) {
314 pr_err("%s: Lookup failed for %s\n", __func__,
315 lookup->name);
316 return rc;
317 }
318 rc = msm_adc_translate_hwmon_to_dal(msm_adc, &target,
319 &lookup->chan_idx);
320 if (rc)
321 pr_err("%s: Translation failed for %s\n", __func__,
322 lookup->name);
323 } else {
324 pr_err("%s: Lookup failed for %s\n", __func__, lookup->name);
325 rc = -EINVAL;
326 }
327 return rc;
328}
329
330static int msm_adc_aio_conversion(struct msm_adc_drv *msm_adc,
331 struct adc_chan_result *request,
332 struct msm_client_data *client)
333{
334 struct msm_adc_platform_data *pdata =
335 msm_adc_drv->pdev->dev.platform_data;
336 struct msm_adc_channels *channel = &pdata->channel[request->chan];
337 struct adc_conv_slot *slot;
338
339 /* we could block here, but only for a bounded time */
340 channel->adc_access_fn->adc_slot_request(channel->adc_dev_instance,
341 &slot);
342
343 if (slot) {
344 atomic_inc(&msm_adc->total_outst);
345 mutex_lock(&client->lock);
346 client->num_outstanding++;
347 mutex_unlock(&client->lock);
348
349 /* indicates non blocking request to callback handler */
350 slot->blocking = 0;
351 slot->compk = NULL;/*For kernel space usage; n/a for usr space*/
352 slot->conv.result.chan = client->adc_chan = request->chan;
353 slot->client = client;
354 slot->adc_request = START_OF_CONV;
355 slot->chan_path = channel->chan_path_type;
356 slot->chan_adc_config = channel->adc_config_type;
357 slot->chan_adc_calib = channel->adc_calib_type;
358 queue_work(msm_adc->wq, &slot->work);
359 return 0;
360 }
361 return -EBUSY;
362}
363
364static int msm_adc_fluid_hw_deinit(struct msm_adc_drv *msm_adc)
365{
366 struct msm_adc_platform_data *pdata = msm_adc->pdev->dev.platform_data;
367
368 if (!epm_init)
369 return -EINVAL;
370
371 if (pdata->gpio_config == APROC_CONFIG &&
372 epm_fluid_enabled && pdata->adc_fluid_disable != NULL) {
373 pdata->adc_fluid_disable();
374 epm_fluid_enabled = false;
375 }
376
377 return 0;
378}
379
380static int msm_adc_fluid_hw_init(struct msm_adc_drv *msm_adc)
381{
382 struct msm_adc_platform_data *pdata = msm_adc->pdev->dev.platform_data;
383
384 if (!epm_init)
385 return -EINVAL;
386
387 if (!pdata->adc_fluid_enable)
388 return -ENODEV;
389
390 printk(KERN_DEBUG "msm_adc_fluid_hw_init: Calling adc_fluid_enable.\n");
391
392 if (pdata->gpio_config == APROC_CONFIG && !epm_fluid_enabled) {
393 pdata->adc_fluid_enable();
394 epm_fluid_enabled = true;
395 }
396
397 /* return success for now but check for errors from hw init configuration */
398 return 0;
399}
400
401static int msm_adc_poll_complete(struct msm_adc_drv *msm_adc,
402 struct msm_client_data *client, uint32_t *pending)
403{
404 int rc;
405
406 /*
407 * Don't proceed if there there's nothing queued on this client.
408 * We could deadlock otherwise in a single threaded scenario.
409 */
410 if (no_pending_client_requests(client) && !data_avail(client, pending))
411 return -EDEADLK;
412
413 rc = wait_event_interruptible(client->data_wait,
414 data_avail(client, pending));
415 if (rc)
416 return rc;
417
418 return 0;
419}
420
421static int msm_adc_read_result(struct msm_adc_drv *msm_adc,
422 struct msm_client_data *client,
423 struct adc_chan_result *result)
424{
425 struct msm_adc_platform_data *pdata = msm_adc->pdev->dev.platform_data;
426 struct msm_adc_channels *channel = pdata->channel;
427 struct adc_conv_slot *slot;
428 int rc = 0;
429
430 mutex_lock(&client->lock);
431
432 slot = list_first_entry(&client->complete_list,
433 struct adc_conv_slot, list);
434 if (!slot) {
435 mutex_unlock(&client->lock);
436 return -ENOMSG;
437 }
438
439 slot->client = NULL;
440 list_del(&slot->list);
441
442 client->num_complete--;
443
444 mutex_unlock(&client->lock);
445
446 *result = slot->conv.result;
447
448 /* restore this slot to reserve */
449 channel[slot->conv.result.chan].adc_access_fn->adc_restore_slot(
450 channel[slot->conv.result.chan].adc_dev_instance, slot);
451
452 return rc;
453}
454
455static long msm_adc_ioctl(struct file *file, unsigned int cmd,
456 unsigned long arg)
457{
458 struct msm_client_data *client = file->private_data;
459 struct msm_adc_drv *msm_adc = msm_adc_drv;
460 struct platform_device *pdev = msm_adc->pdev;
461 struct msm_adc_platform_data *pdata = pdev->dev.platform_data;
462 uint32_t block_res = 0;
463
464 int rc;
465
466 switch (cmd) {
467 case MSM_ADC_REQUEST:
468 {
469 struct adc_chan_result conv;
470
471 if (copy_from_user(&conv, (void __user *)arg,
472 sizeof(struct adc_chan_result)))
473 return -EFAULT;
474
475 if (conv.chan < pdata->num_chan_supported) {
476 rc = msm_adc_blocking_conversion(msm_adc,
477 conv.chan, &conv);
478 } else {
479 if (!msm_adc->dev_h)
480 return -EAGAIN;
481
482 rc = msm_rpc_adc_blocking_conversion(msm_adc,
483 conv.chan, &conv);
484 }
485 if (rc) {
486 dev_dbg(&pdev->dev, "BLK conversion failed\n");
487 return rc;
488 }
489
490 if (copy_to_user((void __user *)arg, &conv,
491 sizeof(struct adc_chan_result)))
492 return -EFAULT;
493 break;
494 }
495 case MSM_ADC_AIO_REQUEST_BLOCK_RES:
496 block_res = 1;
497 case MSM_ADC_AIO_REQUEST:
498 {
499 struct adc_chan_result conv;
500
501 if (copy_from_user(&conv, (void __user *)arg,
502 sizeof(struct adc_chan_result)))
503 return -EFAULT;
504
505 if (conv.chan >= pdata->num_chan_supported)
506 return -EINVAL;
507
508 rc = msm_adc_aio_conversion(msm_adc, &conv, client);
509 if (rc) {
510 dev_dbg(&pdev->dev, "AIO conversion failed\n");
511 return rc;
512 }
513 if (copy_to_user((void __user *)arg, &conv,
514 sizeof(struct adc_chan_result)))
515 return -EFAULT;
516 break;
517 }
518 case MSM_ADC_AIO_POLL:
519 {
520 uint32_t completed;
521
522 rc = msm_adc_poll_complete(msm_adc, client, &completed);
523 if (rc) {
524 dev_dbg(&pdev->dev, "poll request failed\n");
525 return rc;
526 }
527
528 if (copy_to_user((void __user *)arg, &completed,
529 sizeof(uint32_t)))
530 return -EFAULT;
531
532 break;
533 }
534 case MSM_ADC_AIO_READ:
535 {
536 struct adc_chan_result result;
537
538 rc = msm_adc_read_result(msm_adc, client, &result);
539 if (rc) {
540 dev_dbg(&pdev->dev, "read result failed\n");
541 return rc;
542 }
543
544 if (copy_to_user((void __user *)arg, &result,
545 sizeof(struct adc_chan_result)))
546 return -EFAULT;
547 break;
548 }
549 case MSM_ADC_LOOKUP:
550 {
551 struct msm_adc_lookup lookup;
552
553 if (copy_from_user(&lookup, (void __user *)arg,
554 sizeof(struct msm_adc_lookup)))
555 return -EFAULT;
556
557 rc = msm_adc_lookup(msm_adc, &lookup);
558 if (rc) {
559 dev_dbg(&pdev->dev, "No such channel: %s\n",
560 lookup.name);
561 return rc;
562 }
563
564 if (copy_to_user((void __user *)arg, &lookup,
565 sizeof(struct msm_adc_lookup)))
566 return -EFAULT;
567 break;
568 }
569 case MSM_ADC_FLUID_INIT:
570 {
571 uint32_t result;
572
573 result = msm_adc_fluid_hw_init(msm_adc);
574
575 if (copy_to_user((void __user *)arg, &result,
576 sizeof(uint32_t))) {
577 printk(KERN_ERR "MSM_ADC_FLUID_INIT: "
578 "copy_to_user returned an error.\n");
579 return -EFAULT;
580 }
581 printk(KERN_DEBUG "MSM_ADC_FLUID_INIT: Success.\n");
582 break;
583 }
584 case MSM_ADC_FLUID_DEINIT:
585 {
586 uint32_t result;
587
588 result = msm_adc_fluid_hw_deinit(msm_adc);
589
590 if (copy_to_user((void __user *)arg, &result,
591 sizeof(uint32_t)))
592 return -EFAULT;
593 break;
594 }
595 default:
596 return -EINVAL;
597 }
598
599 return 0;
600}
601
602const struct file_operations msm_adc_fops = {
603 .open = msm_adc_open,
604 .release = msm_adc_release,
605 .unlocked_ioctl = msm_adc_ioctl,
606};
607
608static ssize_t msm_adc_show_curr(struct device *dev,
609 struct device_attribute *devattr, char *buf)
610{
611 struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
612 struct msm_adc_drv *msm_adc = dev_get_drvdata(dev);
613 struct msm_adc_platform_data *pdata = msm_adc->pdev->dev.platform_data;
614 struct adc_chan_result result;
615 int rc;
616
617#ifdef CONFIG_PMIC8058_XOADC
618 rc = pm8058_xoadc_registered();
619 if (rc <= 0)
620 return -ENODEV;
621#endif
622 if (attr->index < pdata->num_chan_supported) {
623 rc = msm_adc_blocking_conversion(msm_adc,
624 attr->index, &result);
625 } else {
626 if (pdata->gpio_config == APROC_CONFIG && !epm_fluid_enabled
627 && pdata->adc_fluid_enable != NULL) {
628 printk(KERN_DEBUG "This is to read ADC value for "
629 "Fluid EPM and init. Do it only once.\n");
630 pdata->adc_fluid_enable();
631 epm_fluid_enabled = true;
632 }
633 rc = msm_rpc_adc_blocking_conversion(msm_adc,
634 attr->index, &result);
635 }
636 if (rc)
637 return 0;
638
639 return sprintf(buf, "Result: %lld Raw: %d\n", result.physical,
640 result.adc_code);
641}
642
643static int msm_rpc_adc_blocking_conversion(struct msm_adc_drv *msm_adc,
644 uint32_t hwmon_chan, struct adc_chan_result *result)
645{
646 struct msm_adc_platform_data *pdata = msm_adc->pdev->dev.platform_data;
647 struct dal_conv_request params;
648 struct device *dev = &msm_adc->pdev->dev;
649 struct adc_dev *adc_dev;
650 struct dal_conv_state *conv_s;
651 struct dal_conv_slot *slot;
652 struct adc_dev_spec dest;
653 int timeout, rc = 0;
654
655 if (pdata->gpio_config == APROC_CONFIG &&
656 pdata->adc_gpio_enable != NULL)
657 pdata->adc_gpio_enable(hwmon_chan-pdata->num_chan_supported);
658
659 rc = msm_adc_translate_dal_to_hwmon(msm_adc, hwmon_chan, &dest);
660 if (rc) {
661 dev_err(dev, "%s: translation from chan %u failed\n",
662 __func__, hwmon_chan);
663 if (pdata->gpio_config == APROC_CONFIG &&
664 pdata->adc_gpio_disable != NULL)
665 pdata->adc_gpio_disable(hwmon_chan
666 -pdata->num_chan_supported);
667 return -EINVAL;
668 }
669
670 adc_dev = msm_adc->devs[dest.hwmon_dev_idx];
671 conv_s = &adc_dev->conv;
672
673 down(&conv_s->slot_count);
674
675 mutex_lock(&conv_s->list_lock);
676
677 slot = list_first_entry(&conv_s->slots, struct dal_conv_slot, list);
678 list_del(&slot->list);
679 BUG_ON(!slot);
680
681 mutex_unlock(&conv_s->list_lock);
682
683 /* indicates blocking request to callback handler */
684 slot->blocking = 1;
685
686 params.target.dev_idx = dest.dal.dev_idx;
687 params.target.chan_idx = dest.dal.chan_idx;
688 params.cb_h = slot->cb_h;
689
690 rc = dalrpc_fcn_8(MSM_ADC_DALRPC_CMD_REQ_CONV, msm_adc->dev_h,
691 &params, sizeof(params), NULL, 0);
692 if (rc) {
693 dev_err(dev, "%s: Conversion for device = %u channel = %u"
694 " failed\n", __func__, params.target.dev_idx,
695 params.target.chan_idx);
696
697 rc = -EIO;
698 goto blk_conv_err;
699 }
700
701 timeout = wait_for_completion_interruptible_timeout(&slot->comp,
702 MSM_ADC_DALRC_CONV_TIMEOUT);
703 if (timeout == 0) {
704 dev_err(dev, "read for device = %u channel = %u timed out\n",
705 params.target.dev_idx, params.target.chan_idx);
706 rc = -ETIMEDOUT;
707 goto blk_conv_err;
708 } else if (timeout < 0) {
709 rc = -EINTR;
710 goto blk_conv_err;
711 }
712
713 result->physical = (int64_t)slot->result.physical;
714
715 if (slot->result.status == DAL_RESULT_STATUS_INVALID)
716 rc = -ENODATA;
717
718blk_conv_err:
719 if (pdata->gpio_config == APROC_CONFIG &&
720 pdata->adc_gpio_disable != NULL)
721 pdata->adc_gpio_disable(hwmon_chan-pdata->num_chan_supported);
722 msm_adc_restore_slot(conv_s, slot);
723
724 return rc;
725}
726
727static int msm_adc_blocking_conversion(struct msm_adc_drv *msm_adc,
728 uint32_t hwmon_chan, struct adc_chan_result *result)
729{
730 struct adc_conv_slot *slot;
731 struct msm_adc_platform_data *pdata =
732 msm_adc_drv->pdev->dev.platform_data;
733 struct msm_adc_channels *channel = &pdata->channel[hwmon_chan];
Vijayakumar Muthuvel Manickam2d2a2c52011-10-20 13:41:39 -0700734 int ret = 0;
735
736 if (conv_first_request) {
737 ret = pm8058_xoadc_calib_device(channel->adc_dev_instance);
738 if (ret) {
739 pr_err("pmic8058 xoadc calibration failed, retry\n");
740 return ret;
741 }
742 conv_first_request = false;
743 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700744
745 channel->adc_access_fn->adc_slot_request(channel->adc_dev_instance,
746 &slot);
747 if (slot) {
748 slot->conv.result.chan = hwmon_chan;
749 /* indicates blocking request to callback handler */
750 slot->blocking = 1;
751 slot->adc_request = START_OF_CONV;
752 slot->chan_path = channel->chan_path_type;
753 slot->chan_adc_config = channel->adc_config_type;
754 slot->chan_adc_calib = channel->adc_calib_type;
755 queue_work(msm_adc_drv->wq, &slot->work);
756
757 wait_for_completion_interruptible(&slot->comp);
758 *result = slot->conv.result;
759 channel->adc_access_fn->adc_restore_slot(
760 channel->adc_dev_instance, slot);
761 return 0;
762 }
763 return -EBUSY;
764}
765
766int32_t adc_channel_open(uint32_t channel, void **h)
767{
768 struct msm_client_data *client;
769 struct msm_adc_drv *msm_adc = msm_adc_drv;
770 struct msm_adc_platform_data *pdata;
771 struct platform_device *pdev;
772 int i = 0;
773
774 if (!msm_adc_drv)
775 return -EFAULT;
776
777#ifdef CONFIG_PMIC8058_XOADC
778 if (pm8058_xoadc_registered() <= 0)
779 return -ENODEV;
780#endif
781 pdata = msm_adc->pdev->dev.platform_data;
782 pdev = msm_adc->pdev;
783
784 while (i < pdata->num_chan_supported) {
785 if (channel == pdata->channel[i].channel_name)
786 break;
787 else
788 i++;
789 }
790
791 if (i == pdata->num_chan_supported)
792 return -EBADF; /* unknown channel */
793
794 client = kzalloc(sizeof(struct msm_client_data), GFP_KERNEL);
795 if (!client) {
796 dev_err(&pdev->dev, "Unable to allocate memory\n");
797 return -ENOMEM;
798 }
799
800 if (!try_module_get(THIS_MODULE)) {
801 kfree(client);
802 return -EACCES;
803 }
804
805 mutex_init(&client->lock);
806 INIT_LIST_HEAD(&client->complete_list);
807 init_waitqueue_head(&client->data_wait);
808 init_waitqueue_head(&client->outst_wait);
809
810 client->online = 1;
811 client->adc_chan = i;
812 *h = (void *)client;
813 return 0;
814}
815
816int32_t adc_channel_close(void *h)
817{
818 struct msm_client_data *client = (struct msm_client_data *)h;
819
820 kfree(client);
821 return 0;
822}
823
824int32_t adc_channel_request_conv(void *h, struct completion *conv_complete_evt)
825{
826 struct msm_client_data *client = (struct msm_client_data *)h;
827 struct msm_adc_platform_data *pdata =
828 msm_adc_drv->pdev->dev.platform_data;
829 struct msm_adc_channels *channel = &pdata->channel[client->adc_chan];
830 struct adc_conv_slot *slot;
Vijayakumar Muthuvel Manickam2d2a2c52011-10-20 13:41:39 -0700831 int ret;
832
833 if (conv_first_request) {
834 ret = pm8058_xoadc_calib_device(channel->adc_dev_instance);
835 if (ret) {
836 pr_err("pmic8058 xoadc calibration failed, retry\n");
837 return ret;
838 }
839 conv_first_request = false;
840 }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700841
842 channel->adc_access_fn->adc_slot_request(channel->adc_dev_instance,
843 &slot);
844
845 if (slot) {
846 atomic_inc(&msm_adc_drv->total_outst);
847 mutex_lock(&client->lock);
848 client->num_outstanding++;
849 mutex_unlock(&client->lock);
850
851 slot->conv.result.chan = client->adc_chan;
852 slot->blocking = 0;
853 slot->compk = conv_complete_evt;
854 slot->client = client;
855 slot->adc_request = START_OF_CONV;
856 slot->chan_path = channel->chan_path_type;
857 slot->chan_adc_config = channel->adc_config_type;
858 slot->chan_adc_calib = channel->adc_calib_type;
859 queue_work(msm_adc_drv->wq, &slot->work);
860 return 0;
861 }
862 return -EBUSY;
863}
864
865int32_t adc_channel_read_result(void *h, struct adc_chan_result *chan_result)
866{
867 struct msm_client_data *client = (struct msm_client_data *)h;
868 struct msm_adc_platform_data *pdata =
869 msm_adc_drv->pdev->dev.platform_data;
870 struct msm_adc_channels *channel = pdata->channel;
871 struct adc_conv_slot *slot;
872 int rc = 0;
873
874 mutex_lock(&client->lock);
875
876 slot = list_first_entry(&client->complete_list,
877 struct adc_conv_slot, list);
878 if (!slot) {
879 mutex_unlock(&client->lock);
880 return -ENOMSG;
881 }
882
883 slot->client = NULL;
884 list_del(&slot->list);
885
886 client->num_complete--;
887
888 mutex_unlock(&client->lock);
889
890 *chan_result = slot->conv.result;
891
892 /* restore this slot to reserve */
893 channel[slot->conv.result.chan].adc_access_fn->adc_restore_slot(
894 channel[slot->conv.result.chan].adc_dev_instance, slot);
895
896 return rc;
897}
898
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700899static void msm_rpc_adc_conv_cb(void *context, u32 param,
900 void *evt_buf, u32 len)
901{
902 struct dal_adc_result *result = evt_buf;
903 struct dal_conv_slot *slot = context;
904 struct msm_adc_drv *msm_adc = msm_adc_drv;
905
906 memcpy(&slot->result, result, sizeof(slot->result));
907
908 /* for blocking requests, signal complete */
909 if (slot->blocking)
910 complete(&slot->comp);
911
912 /* for non-blocking requests, add slot to the client completed list */
913 else {
914 struct msm_client_data *client = slot->client;
915
916 mutex_lock(&client->lock);
917
918 list_add(&slot->list, &client->complete_list);
919 client->num_complete++;
920 client->num_outstanding--;
921
922 /*
923 * if the client release has been invoked and this is call
924 * corresponds to the last request, then signal release
925 * to complete.
926 */
927 if (slot->client->online == 0 && client->num_outstanding == 0)
928 wake_up_interruptible_all(&client->outst_wait);
929
930 mutex_unlock(&client->lock);
931
932 wake_up_interruptible_all(&client->data_wait);
933
934 atomic_dec(&msm_adc->total_outst);
935
936 /* verify driver remove has not been invoked */
937 if (atomic_read(&msm_adc->online) == 0 &&
938 atomic_read(&msm_adc->total_outst) == 0)
939 wake_up_interruptible_all(&msm_adc->total_outst_wait);
940 }
941}
942
943void msm_adc_conv_cb(void *context, u32 param,
944 void *evt_buf, u32 len)
945{
946 struct adc_conv_slot *slot = context;
947 struct msm_adc_drv *msm_adc = msm_adc_drv;
948
949 switch (slot->adc_request) {
950 case START_OF_CONV:
951 slot->adc_request = END_OF_CONV;
952 break;
953 case START_OF_CALIBRATION:
954 slot->adc_request = END_OF_CALIBRATION;
955 break;
956 case END_OF_CALIBRATION:
957 case END_OF_CONV:
958 break;
959 }
960 queue_work(msm_adc->wq, &slot->work);
961}
962
963static void msm_adc_teardown_device_conv(struct platform_device *pdev,
964 struct adc_dev *adc_dev)
965{
966 struct dal_conv_state *conv_s = &adc_dev->conv;
967 struct msm_adc_drv *msm_adc = platform_get_drvdata(pdev);
968 struct dal_conv_slot *slot;
969 int i;
970
971 for (i = 0; i < MSM_ADC_DEV_MAX_INFLIGHT; i++) {
972 slot = &conv_s->context[i];
973 if (slot->cb_h) {
974 dalrpc_dealloc_cb(msm_adc->dev_h, slot->cb_h);
975 slot->cb_h = NULL;
976 }
977 }
978}
979
980static void msm_rpc_adc_teardown_device(struct platform_device *pdev,
981 struct adc_dev *adc_dev)
982{
983 struct dal_translation *transl = &adc_dev->transl;
984 int i, num_chans = transl->hwmon_end - transl->hwmon_start + 1;
985
986 if (adc_dev->sens_attr)
987 for (i = 0; i < num_chans; i++)
988 device_remove_file(&pdev->dev,
989 &adc_dev->sens_attr[i].dev_attr);
990
991 msm_adc_teardown_device_conv(pdev, adc_dev);
992
993 kfree(adc_dev->fnames);
994 kfree(adc_dev->sens_attr);
995 kfree(adc_dev);
996}
997
998static void msm_rpc_adc_teardown_devices(struct platform_device *pdev)
999{
1000 struct msm_adc_platform_data *pdata = pdev->dev.platform_data;
1001 struct msm_adc_drv *msm_adc = platform_get_drvdata(pdev);
1002 int i, rc = 0;
1003
1004 for (i = 0; i < pdata->num_adc; i++) {
1005 if (msm_adc->devs[i]) {
1006 msm_rpc_adc_teardown_device(pdev, msm_adc->devs[i]);
1007 msm_adc->devs[i] = NULL;
1008 } else
1009 break;
1010 }
1011
1012 if (msm_adc->dev_h) {
1013 rc = daldevice_detach(msm_adc->dev_h);
1014 if (rc)
1015 dev_err(&pdev->dev, "Cannot detach from dal device\n");
1016 msm_adc->dev_h = NULL;
1017 }
1018
1019}
1020
1021static void msm_adc_teardown_device(struct platform_device *pdev,
1022 struct msm_adc_drv *msm_adc)
1023{
1024 struct msm_adc_platform_data *pdata = pdev->dev.platform_data;
1025 int i, num_chans = pdata->num_chan_supported;
1026
1027 if (pdata->num_chan_supported > 0) {
1028 if (msm_adc->sens_attr)
1029 for (i = 0; i < num_chans; i++)
1030 device_remove_file(&pdev->dev,
1031 &msm_adc->sens_attr[i].dev_attr);
1032 kfree(msm_adc->sens_attr);
1033 }
1034}
1035
1036static void msm_adc_teardown(struct platform_device *pdev)
1037{
1038 struct msm_adc_drv *msm_adc = platform_get_drvdata(pdev);
1039
1040 if (!msm_adc)
1041 return;
1042
1043 misc_deregister(&msm_adc->misc);
1044
1045 if (msm_adc->hwmon)
1046 hwmon_device_unregister(msm_adc->hwmon);
1047
1048 msm_rpc_adc_teardown_devices(pdev);
1049 msm_adc_teardown_device(pdev, msm_adc);
1050
1051 kfree(msm_adc);
1052 platform_set_drvdata(pdev, NULL);
1053}
1054
1055static int __devinit msm_adc_device_conv_init(struct msm_adc_drv *msm_adc,
1056 struct adc_dev *adc_dev)
1057{
1058 struct platform_device *pdev = msm_adc->pdev;
1059 struct dal_conv_state *conv_s = &adc_dev->conv;
1060 struct dal_conv_slot *slot = conv_s->context;
1061 int rc, i;
1062
1063 sema_init(&conv_s->slot_count, MSM_ADC_DEV_MAX_INFLIGHT);
1064 mutex_init(&conv_s->list_lock);
1065 INIT_LIST_HEAD(&conv_s->slots);
1066
1067 for (i = 0; i < MSM_ADC_DEV_MAX_INFLIGHT; i++) {
1068 list_add(&slot->list, &conv_s->slots);
1069 slot->cb_h = dalrpc_alloc_cb(msm_adc->dev_h,
1070 msm_rpc_adc_conv_cb, slot);
1071 if (!slot->cb_h) {
1072 dev_err(&pdev->dev, "Unable to allocate DAL callback"
1073 " for slot %d\n", i);
1074 rc = -ENOMEM;
1075 goto dal_err_cb;
1076 }
1077 init_completion(&slot->comp);
1078 slot->idx = i;
1079 slot++;
1080 }
1081
1082 return 0;
1083
1084dal_err_cb:
1085 msm_adc_teardown_device_conv(pdev, adc_dev);
1086
1087 return rc;
1088}
1089
1090static struct sensor_device_attribute msm_rpc_adc_curr_in_attr =
1091 SENSOR_ATTR(NULL, S_IRUGO, msm_adc_show_curr, NULL, 0);
1092
1093static int __devinit msm_rpc_adc_device_init_hwmon(struct platform_device *pdev,
1094 struct adc_dev *adc_dev)
1095{
1096 struct dal_translation *transl = &adc_dev->transl;
1097 int i, rc, num_chans = transl->hwmon_end - transl->hwmon_start + 1;
1098 const char prefix[] = "curr", postfix[] = "_input";
1099 char tmpbuf[5];
1100
1101 adc_dev->fnames = kzalloc(num_chans * MSM_ADC_MAX_FNAME +
1102 num_chans * sizeof(char *), GFP_KERNEL);
1103 if (!adc_dev->fnames) {
1104 dev_err(&pdev->dev, "Unable to allocate memory\n");
1105 return -ENOMEM;
1106 }
1107
1108 adc_dev->sens_attr = kzalloc(num_chans *
1109 sizeof(struct sensor_device_attribute), GFP_KERNEL);
1110 if (!adc_dev->sens_attr) {
1111 dev_err(&pdev->dev, "Unable to allocate memory\n");
1112 rc = -ENOMEM;
1113 goto hwmon_err_fnames;
1114 }
1115
1116 for (i = 0; i < num_chans; i++) {
1117 adc_dev->fnames[i] = (char *)adc_dev->fnames +
1118 i * MSM_ADC_MAX_FNAME + num_chans * sizeof(char *);
1119 strcpy(adc_dev->fnames[i], prefix);
1120 sprintf(tmpbuf, "%d", transl->hwmon_start + i);
1121 strcat(adc_dev->fnames[i], tmpbuf);
1122 strcat(adc_dev->fnames[i], postfix);
1123
1124 msm_rpc_adc_curr_in_attr.index = transl->hwmon_start + i;
1125 msm_rpc_adc_curr_in_attr.dev_attr.attr.name =
1126 adc_dev->fnames[i];
1127 memcpy(&adc_dev->sens_attr[i], &msm_rpc_adc_curr_in_attr,
1128 sizeof(msm_rpc_adc_curr_in_attr));
1129
1130 rc = device_create_file(&pdev->dev,
1131 &adc_dev->sens_attr[i].dev_attr);
1132 if (rc) {
1133 dev_err(&pdev->dev, "device_create_file failed for "
1134 "dal dev %u chan %d\n",
1135 adc_dev->transl.dal_dev_idx, i);
1136 goto hwmon_err_sens;
1137 }
1138 }
1139
1140 return 0;
1141
1142hwmon_err_sens:
1143 kfree(adc_dev->sens_attr);
1144hwmon_err_fnames:
1145 kfree(adc_dev->fnames);
1146
1147 return rc;
1148}
1149
1150static int __devinit msm_rpc_adc_device_init(struct platform_device *pdev)
1151{
1152 struct msm_adc_platform_data *pdata = pdev->dev.platform_data;
1153 struct msm_adc_drv *msm_adc = platform_get_drvdata(pdev);
1154 struct adc_dev *adc_dev;
1155 struct adc_dev_spec target;
1156 int i, rc;
1157 int hwmon_cntr = pdata->num_chan_supported;
1158
1159 for (i = 0; i < pdata->num_adc; i++) {
1160 adc_dev = kzalloc(sizeof(struct adc_dev), GFP_KERNEL);
1161 if (!adc_dev) {
1162 dev_err(&pdev->dev, "Unable to allocate memory\n");
1163 rc = -ENOMEM;
1164 goto dev_init_err;
1165 }
1166
1167 msm_adc->devs[i] = adc_dev;
1168 adc_dev->name = pdata->dev_names[i];
1169
1170 rc = msm_adc_device_conv_init(msm_adc, adc_dev);
1171 if (rc) {
1172 dev_err(&pdev->dev, "DAL device[%s] failed conv init\n",
1173 adc_dev->name);
1174 goto dev_init_err;
1175 }
1176
Siddartha Mohanadossbc2103f2012-03-20 11:41:48 -07001177 if (!pdata->target_hw == MSM_8x25) {
1178 /* DAL device lookup */
1179 rc = msm_adc_getinputproperties(msm_adc, adc_dev->name,
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001180 &target);
Siddartha Mohanadossbc2103f2012-03-20 11:41:48 -07001181 if (rc) {
1182 dev_err(&pdev->dev, "No such DAL device[%s]\n",
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001183 adc_dev->name);
Siddartha Mohanadossbc2103f2012-03-20 11:41:48 -07001184 goto dev_init_err;
1185 }
1186
1187 adc_dev->transl.dal_dev_idx = target.dal.dev_idx;
1188 adc_dev->nchans = target.dal.chan_idx;
1189 } else {
1190 /* On targets prior to MSM7x30 the remote driver has
1191 only the channel list and no device id. */
1192 adc_dev->transl.dal_dev_idx = MSM_8x25_ADC_DEV_ID;
1193 adc_dev->nchans = MSM_8x25_CHAN_ID;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001194 }
1195
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001196 adc_dev->transl.hwmon_dev_idx = i;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001197 adc_dev->transl.hwmon_start = hwmon_cntr;
1198 adc_dev->transl.hwmon_end = hwmon_cntr + adc_dev->nchans - 1;
1199 hwmon_cntr += adc_dev->nchans;
1200
1201 rc = msm_rpc_adc_device_init_hwmon(pdev, adc_dev);
1202 if (rc)
1203 goto dev_init_err;
1204 }
1205
1206 return 0;
1207
1208dev_init_err:
1209 msm_rpc_adc_teardown_devices(pdev);
1210 return rc;
1211}
1212
1213static int __devinit msm_rpc_adc_init(struct platform_device *pdev1)
1214{
1215 struct msm_adc_drv *msm_adc = msm_adc_drv;
1216 struct platform_device *pdev = msm_adc->pdev;
1217 struct msm_adc_platform_data *pdata = pdev->dev.platform_data;
1218 int rc = 0;
1219
1220 dev_dbg(&pdev->dev, "msm_rpc_adc_init called\n");
1221
1222 if (!pdata) {
1223 dev_err(&pdev->dev, "no platform data?\n");
1224 return -EINVAL;
1225 }
1226
1227 mutex_init(&msm_adc->prop_lock);
1228
1229 rc = daldevice_attach(MSM_ADC_DALRPC_DEVICEID,
1230 MSM_ADC_DALRPC_PORT_NAME,
1231 MSM_ADC_DALRPC_CPU,
1232 &msm_adc->dev_h);
1233 if (rc) {
1234 dev_err(&pdev->dev, "Cannot attach to dal device\n");
1235 return rc;
1236 }
1237
1238 dev_dbg(&pdev->dev, "Attach to dal device Succeeded\n");
1239
1240 rc = msm_rpc_adc_device_init(pdev);
1241 if (rc) {
1242 dev_err(&pdev->dev, "msm_adc_dev_init failed\n");
1243 goto err_cleanup;
1244 }
1245
1246 init_waitqueue_head(&msm_adc->rpc_total_outst_wait);
1247 atomic_set(&msm_adc->rpc_online, 1);
1248 atomic_set(&msm_adc->rpc_total_outst, 0);
1249 epm_init = true;
1250 pr_info("msm_adc successfully registered\n");
1251
1252 return 0;
1253
1254err_cleanup:
1255 msm_rpc_adc_teardown_devices(pdev);
1256
1257 return rc;
1258}
1259
1260/*
1261 * Process the deferred job
1262 */
1263void msm_adc_wq_work(struct work_struct *work)
1264{
1265 struct adc_properties *adc_properties;
1266 struct adc_conv_slot *slot = container_of(work,
1267 struct adc_conv_slot, work);
1268 uint32_t idx = slot->conv.result.chan;
1269 struct msm_adc_platform_data *pdata =
1270 msm_adc_drv->pdev->dev.platform_data;
1271 struct msm_adc_channels *channel = &pdata->channel[idx];
1272 int32_t adc_code;
1273
1274 switch (slot->adc_request) {
1275 case START_OF_CONV:
1276 channel->adc_access_fn->adc_select_chan_and_start_conv(
1277 channel->adc_dev_instance, slot);
1278 break;
1279 case END_OF_CONV:
1280 adc_properties = channel->adc_access_fn->adc_get_properties(
1281 channel->adc_dev_instance);
1282 if (channel->adc_access_fn->adc_read_adc_code)
1283 channel->adc_access_fn->adc_read_adc_code(
1284 channel->adc_dev_instance, &adc_code);
1285 if (channel->chan_processor)
1286 channel->chan_processor(adc_code, adc_properties,
1287 &slot->chan_properties, &slot->conv.result);
1288 /* Intentionally a fall thru here. Calibraton does not need
1289 to perform channel processing, etc. However, both
1290 end of conversion and end of calibration requires the below
1291 fall thru code to be executed. */
1292 case END_OF_CALIBRATION:
1293 /* for blocking requests, signal complete */
1294 if (slot->blocking)
1295 complete(&slot->comp);
1296 else {
1297 struct msm_client_data *client = slot->client;
1298
1299 mutex_lock(&client->lock);
1300
1301 if (slot->adc_request == END_OF_CONV) {
1302 list_add(&slot->list, &client->complete_list);
1303 client->num_complete++;
1304 }
1305 client->num_outstanding--;
1306
1307 /*
1308 * if the client release has been invoked and this is call
1309 * corresponds to the last request, then signal release
1310 * to complete.
1311 */
1312 if (slot->client->online == 0 &&
1313 client->num_outstanding == 0)
1314 wake_up_interruptible_all(&client->outst_wait);
1315
1316 mutex_unlock(&client->lock);
1317
1318 wake_up_interruptible_all(&client->data_wait);
1319
1320 atomic_dec(&msm_adc_drv->total_outst);
1321
1322 /* verify driver remove has not been invoked */
1323 if (atomic_read(&msm_adc_drv->online) == 0 &&
1324 atomic_read(&msm_adc_drv->total_outst) == 0)
1325 wake_up_interruptible_all(
1326 &msm_adc_drv->total_outst_wait);
1327
1328 if (slot->compk) /* Kernel space request */
1329 complete(slot->compk);
1330 if (slot->adc_request == END_OF_CALIBRATION)
1331 channel->adc_access_fn->adc_restore_slot(
1332 channel->adc_dev_instance, slot);
1333 }
1334 break;
1335 case START_OF_CALIBRATION: /* code here to please code reviewers
1336 to satisfy silly compiler warnings */
1337 break;
1338 }
1339}
1340
1341static struct sensor_device_attribute msm_adc_curr_in_attr =
1342 SENSOR_ATTR(NULL, S_IRUGO, msm_adc_show_curr, NULL, 0);
1343
1344static int __devinit msm_adc_init_hwmon(struct platform_device *pdev,
1345 struct msm_adc_drv *msm_adc)
1346{
1347 struct msm_adc_platform_data *pdata = pdev->dev.platform_data;
1348 struct msm_adc_channels *channel = pdata->channel;
1349 int i, rc, num_chans = pdata->num_chan_supported;
1350
1351 if (!channel)
1352 return -EINVAL;
1353
1354 msm_adc->sens_attr = kzalloc(num_chans *
1355 sizeof(struct sensor_device_attribute), GFP_KERNEL);
1356 if (!msm_adc->sens_attr) {
1357 dev_err(&pdev->dev, "Unable to allocate memory\n");
1358 rc = -ENOMEM;
1359 goto hwmon_err_sens;
1360 }
1361
1362 for (i = 0; i < num_chans; i++) {
1363 msm_adc_curr_in_attr.index = i;
1364 msm_adc_curr_in_attr.dev_attr.attr.name = channel[i].name;
1365 memcpy(&msm_adc->sens_attr[i], &msm_adc_curr_in_attr,
1366 sizeof(msm_adc_curr_in_attr));
1367
1368 rc = device_create_file(&pdev->dev,
1369 &msm_adc->sens_attr[i].dev_attr);
1370 if (rc) {
1371 dev_err(&pdev->dev, "device_create_file failed for "
1372 "dal dev %s\n",
1373 channel[i].name);
1374 goto hwmon_err_sens;
1375 }
1376 }
1377
1378 return 0;
1379
1380hwmon_err_sens:
1381 kfree(msm_adc->sens_attr);
1382
1383 return rc;
1384}
1385
1386static struct platform_driver msm_adc_rpcrouter_remote_driver = {
1387 .probe = msm_rpc_adc_init,
1388 .driver = {
1389 .name = MSM_ADC_DALRPC_PORT_NAME,
1390 .owner = THIS_MODULE,
1391 },
1392};
1393
Stephen Boyd3c9bd8f2012-02-21 23:49:06 -08001394static int __devinit msm_adc_probe(struct platform_device *pdev)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001395{
1396 struct msm_adc_platform_data *pdata = pdev->dev.platform_data;
1397 struct msm_adc_drv *msm_adc;
1398 int rc = 0;
1399
1400 if (!pdata) {
1401 dev_err(&pdev->dev, "no platform data?\n");
1402 return -EINVAL;
1403 }
1404
1405 msm_adc = kzalloc(sizeof(struct msm_adc_drv), GFP_KERNEL);
1406 if (!msm_adc) {
1407 dev_err(&pdev->dev, "Unable to allocate memory\n");
1408 return -ENOMEM;
1409 }
1410
1411 platform_set_drvdata(pdev, msm_adc);
1412 msm_adc_drv = msm_adc;
1413 msm_adc->pdev = pdev;
1414
1415 if (pdata->target_hw == MSM_8x60 || pdata->target_hw == FSM_9xxx) {
1416 rc = msm_adc_init_hwmon(pdev, msm_adc);
1417 if (rc) {
1418 dev_err(&pdev->dev, "msm_adc_dev_init failed\n");
1419 goto err_cleanup;
1420 }
1421 }
1422
1423 msm_adc->hwmon = hwmon_device_register(&pdev->dev);
1424 if (IS_ERR(msm_adc->hwmon)) {
1425 dev_err(&pdev->dev, "hwmon_device_register failed\n");
1426 rc = PTR_ERR(msm_adc->hwmon);
1427 goto err_cleanup;
1428 }
1429
1430 msm_adc->misc.name = MSM_ADC_DRIVER_NAME;
1431 msm_adc->misc.minor = MISC_DYNAMIC_MINOR;
1432 msm_adc->misc.fops = &msm_adc_fops;
1433
1434 if (misc_register(&msm_adc->misc)) {
1435 dev_err(&pdev->dev, "Unable to register misc device!\n");
1436 goto err_cleanup;
1437 }
1438
1439 init_waitqueue_head(&msm_adc->total_outst_wait);
1440 atomic_set(&msm_adc->online, 1);
1441 atomic_set(&msm_adc->total_outst, 0);
1442
1443 msm_adc->wq = create_singlethread_workqueue("msm_adc");
1444 if (!msm_adc->wq)
1445 goto err_cleanup;
1446
1447 if (pdata->num_adc > 0) {
1448 if (pdata->target_hw == MSM_8x60)
1449 platform_driver_register(
1450 &msm_adc_rpcrouter_remote_driver);
1451 else
1452 msm_rpc_adc_init(pdev);
1453 }
Vijayakumar Muthuvel Manickam2d2a2c52011-10-20 13:41:39 -07001454 conv_first_request = true;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001455
1456 pr_info("msm_adc successfully registered\n");
1457
1458 return 0;
1459
1460err_cleanup:
1461 msm_adc_teardown(pdev);
1462
1463 return rc;
1464}
1465
1466static int __devexit msm_adc_remove(struct platform_device *pdev)
1467{
1468 int rc;
1469
1470 struct msm_adc_drv *msm_adc = platform_get_drvdata(pdev);
1471
1472 atomic_set(&msm_adc->online, 0);
1473
1474 atomic_set(&msm_adc->rpc_online, 0);
1475
1476 misc_deregister(&msm_adc->misc);
1477
1478 hwmon_device_unregister(msm_adc->hwmon);
1479 msm_adc->hwmon = NULL;
1480
1481 /*
1482 * We may still have outstanding transactions in flight that have not
1483 * completed. Make sure they're completed before tearing down.
1484 */
1485 rc = wait_event_interruptible(msm_adc->total_outst_wait,
1486 atomic_read(&msm_adc->total_outst) == 0);
1487 if (rc) {
1488 pr_err("%s: wait_event_interruptible failed rc = %d\n",
1489 __func__, rc);
1490 return rc;
1491 }
1492
1493 rc = wait_event_interruptible(msm_adc->rpc_total_outst_wait,
1494 atomic_read(&msm_adc->rpc_total_outst) == 0);
1495 if (rc) {
1496 pr_err("%s: wait_event_interruptible failed rc = %d\n",
1497 __func__, rc);
1498 return rc;
1499 }
1500
1501 msm_adc_teardown(pdev);
1502
1503 pr_info("msm_adc unregistered\n");
1504
1505 return 0;
1506}
1507
1508static struct platform_driver msm_adc_driver = {
1509 .probe = msm_adc_probe,
1510 .remove = __devexit_p(msm_adc_remove),
1511 .driver = {
1512 .name = MSM_ADC_DRIVER_NAME,
1513 .owner = THIS_MODULE,
1514 },
1515};
1516
1517static int __init msm_adc_init(void)
1518{
1519 return platform_driver_register(&msm_adc_driver);
1520}
1521module_init(msm_adc_init);
1522
1523static void __exit msm_adc_exit(void)
1524{
1525 platform_driver_unregister(&msm_adc_driver);
1526}
1527module_exit(msm_adc_exit);
1528
1529MODULE_DESCRIPTION("MSM ADC Driver");
1530MODULE_ALIAS("platform:msm_adc");
1531MODULE_LICENSE("GPL v2");
1532MODULE_VERSION("0.1");