diff options
Diffstat (limited to 'drivers/mfd/pcf50633-adc.c')
-rw-r--r-- | drivers/mfd/pcf50633-adc.c | 55 |
1 files changed, 23 insertions, 32 deletions
diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c index fe8f922f665..bf77c8f9f6a 100644 --- a/drivers/mfd/pcf50633-adc.c +++ b/drivers/mfd/pcf50633-adc.c @@ -30,13 +30,13 @@ struct pcf50633_adc_request { int mux; int avg; - int result; void (*callback)(struct pcf50633 *, void *, int); void *callback_param; +}; - /* Used in case of sync requests */ +struct pcf50633_adc_sync_request { + int result; struct completion completion; - }; #define PCF50633_MAX_ADC_FIFO_DEPTH 8 @@ -51,11 +51,6 @@ struct pcf50633_adc { struct mutex queue_mutex; }; -static inline struct pcf50633_adc *__to_adc(struct pcf50633 *pcf) -{ - return platform_get_drvdata(pcf->adc_pdev); -} - static void adc_setup(struct pcf50633 *pcf, int channel, int avg) { channel &= PCF50633_ADCC1_ADCMUX_MASK; @@ -71,7 +66,7 @@ static void adc_setup(struct pcf50633 *pcf, int channel, int avg) static void trigger_next_adc_job_if_any(struct pcf50633 *pcf) { - struct pcf50633_adc *adc = __to_adc(pcf); + struct pcf50633_adc *adc = pcf->adc; int head; head = adc->queue_head; @@ -85,7 +80,7 @@ static void trigger_next_adc_job_if_any(struct pcf50633 *pcf) static int adc_enqueue_request(struct pcf50633 *pcf, struct pcf50633_adc_request *req) { - struct pcf50633_adc *adc = __to_adc(pcf); + struct pcf50633_adc *adc = pcf->adc; int head, tail; mutex_lock(&adc->queue_mutex); @@ -109,10 +104,10 @@ adc_enqueue_request(struct pcf50633 *pcf, struct pcf50633_adc_request *req) return 0; } -static void -pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, int result) +static void pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, + int result) { - struct pcf50633_adc_request *req = param; + struct pcf50633_adc_sync_request *req = param; req->result = result; complete(&req->completion); @@ -120,28 +115,19 @@ pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, int result) int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg) { - struct pcf50633_adc_request *req; - int err; + struct pcf50633_adc_sync_request req; + int ret; - /* req is freed when the result is ready, in interrupt handler */ - req = kzalloc(sizeof(*req), GFP_KERNEL); - if (!req) - return -ENOMEM; - - req->mux = mux; - req->avg = avg; - req->callback = pcf50633_adc_sync_read_callback; - req->callback_param = req; + init_completion(&req.completion); - init_completion(&req->completion); - err = adc_enqueue_request(pcf, req); - if (err) - return err; + ret = pcf50633_adc_async_read(pcf, mux, avg, + pcf50633_adc_sync_read_callback, &req); + if (ret) + return ret; - wait_for_completion(&req->completion); + wait_for_completion(&req.completion); - /* FIXME by this time req might be already freed */ - return req->result; + return req.result; } EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read); @@ -210,13 +196,14 @@ static void pcf50633_adc_irq(int irq, void *data) static int __devinit pcf50633_adc_probe(struct platform_device *pdev) { + struct pcf50633 *pcf = dev_to_pcf50633(pdev->dev.parent); struct pcf50633_adc *adc; adc = kzalloc(sizeof(*adc), GFP_KERNEL); if (!adc) return -ENOMEM; - adc->pcf = dev_to_pcf50633(pdev->dev.parent); + adc->pcf = pcf; platform_set_drvdata(pdev, adc); pcf50633_register_irq(adc->pcf, PCF50633_IRQ_ADCRDY, @@ -224,6 +211,8 @@ static int __devinit pcf50633_adc_probe(struct platform_device *pdev) mutex_init(&adc->queue_mutex); + pcf->adc = adc; + return 0; } @@ -232,6 +221,8 @@ static int __devexit pcf50633_adc_remove(struct platform_device *pdev) struct pcf50633_adc *adc = platform_get_drvdata(pdev); int i, head; + adc->pcf->adc = NULL; + pcf50633_free_irq(adc->pcf, PCF50633_IRQ_ADCRDY); mutex_lock(&adc->queue_mutex); |