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