1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* NXP PCF50633 ADC Driver
4 * (C) 2006-2008 by Openmoko, Inc.
5 * Author: Balaji Rao <balajirrao@openmoko.org>
8 * Broken down from monstrous PCF50633 driver mainly by
9 * Harald Welte, Andy Green and Werner Almesberger
11 * NOTE: This driver does not yet support subtractive ADC mode, which means
12 * you can do only one measurement per read request.
15 #include <linux/kernel.h>
16 #include <linux/slab.h>
17 #include <linux/module.h>
18 #include <linux/device.h>
19 #include <linux/platform_device.h>
20 #include <linux/completion.h>
22 #include <linux/mfd/pcf50633/core.h>
23 #include <linux/mfd/pcf50633/adc.h>
25 struct pcf50633_adc_request
{
28 void (*callback
)(struct pcf50633
*, void *, int);
32 struct pcf50633_adc_sync_request
{
34 struct completion completion
;
37 #define PCF50633_MAX_ADC_FIFO_DEPTH 8
43 struct pcf50633_adc_request
*queue
[PCF50633_MAX_ADC_FIFO_DEPTH
];
46 struct mutex queue_mutex
;
49 static inline struct pcf50633_adc
*__to_adc(struct pcf50633
*pcf
)
51 return platform_get_drvdata(pcf
->adc_pdev
);
54 static void adc_setup(struct pcf50633
*pcf
, int channel
, int avg
)
56 channel
&= PCF50633_ADCC1_ADCMUX_MASK
;
58 /* kill ratiometric, but enable ACCSW biasing */
59 pcf50633_reg_write(pcf
, PCF50633_REG_ADCC2
, 0x00);
60 pcf50633_reg_write(pcf
, PCF50633_REG_ADCC3
, 0x01);
62 /* start ADC conversion on selected channel */
63 pcf50633_reg_write(pcf
, PCF50633_REG_ADCC1
, channel
| avg
|
64 PCF50633_ADCC1_ADCSTART
| PCF50633_ADCC1_RES_10BIT
);
67 static void trigger_next_adc_job_if_any(struct pcf50633
*pcf
)
69 struct pcf50633_adc
*adc
= __to_adc(pcf
);
72 head
= adc
->queue_head
;
74 if (!adc
->queue
[head
])
77 adc_setup(pcf
, adc
->queue
[head
]->mux
, adc
->queue
[head
]->avg
);
81 adc_enqueue_request(struct pcf50633
*pcf
, struct pcf50633_adc_request
*req
)
83 struct pcf50633_adc
*adc
= __to_adc(pcf
);
86 mutex_lock(&adc
->queue_mutex
);
88 head
= adc
->queue_head
;
89 tail
= adc
->queue_tail
;
91 if (adc
->queue
[tail
]) {
92 mutex_unlock(&adc
->queue_mutex
);
93 dev_err(pcf
->dev
, "ADC queue is full, dropping request\n");
97 adc
->queue
[tail
] = req
;
99 trigger_next_adc_job_if_any(pcf
);
100 adc
->queue_tail
= (tail
+ 1) & (PCF50633_MAX_ADC_FIFO_DEPTH
- 1);
102 mutex_unlock(&adc
->queue_mutex
);
107 static void pcf50633_adc_sync_read_callback(struct pcf50633
*pcf
, void *param
,
110 struct pcf50633_adc_sync_request
*req
= param
;
112 req
->result
= result
;
113 complete(&req
->completion
);
116 int pcf50633_adc_sync_read(struct pcf50633
*pcf
, int mux
, int avg
)
118 struct pcf50633_adc_sync_request req
;
121 init_completion(&req
.completion
);
123 ret
= pcf50633_adc_async_read(pcf
, mux
, avg
,
124 pcf50633_adc_sync_read_callback
, &req
);
128 wait_for_completion(&req
.completion
);
132 EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read
);
134 int pcf50633_adc_async_read(struct pcf50633
*pcf
, int mux
, int avg
,
135 void (*callback
)(struct pcf50633
*, void *, int),
136 void *callback_param
)
138 struct pcf50633_adc_request
*req
;
140 /* req is freed when the result is ready, in interrupt handler */
141 req
= kmalloc(sizeof(*req
), GFP_KERNEL
);
147 req
->callback
= callback
;
148 req
->callback_param
= callback_param
;
150 return adc_enqueue_request(pcf
, req
);
152 EXPORT_SYMBOL_GPL(pcf50633_adc_async_read
);
154 static int adc_result(struct pcf50633
*pcf
)
159 adcs1
= pcf50633_reg_read(pcf
, PCF50633_REG_ADCS1
);
160 adcs3
= pcf50633_reg_read(pcf
, PCF50633_REG_ADCS3
);
161 result
= (adcs1
<< 2) | (adcs3
& PCF50633_ADCS3_ADCDAT1L_MASK
);
163 dev_dbg(pcf
->dev
, "adc result = %d\n", result
);
168 static void pcf50633_adc_irq(int irq
, void *data
)
170 struct pcf50633_adc
*adc
= data
;
171 struct pcf50633
*pcf
= adc
->pcf
;
172 struct pcf50633_adc_request
*req
;
175 mutex_lock(&adc
->queue_mutex
);
176 head
= adc
->queue_head
;
178 req
= adc
->queue
[head
];
180 dev_err(pcf
->dev
, "pcf50633-adc irq: ADC queue empty!\n");
181 mutex_unlock(&adc
->queue_mutex
);
184 adc
->queue
[head
] = NULL
;
185 adc
->queue_head
= (head
+ 1) &
186 (PCF50633_MAX_ADC_FIFO_DEPTH
- 1);
188 res
= adc_result(pcf
);
189 trigger_next_adc_job_if_any(pcf
);
191 mutex_unlock(&adc
->queue_mutex
);
193 req
->callback(pcf
, req
->callback_param
, res
);
197 static int pcf50633_adc_probe(struct platform_device
*pdev
)
199 struct pcf50633_adc
*adc
;
201 adc
= devm_kzalloc(&pdev
->dev
, sizeof(*adc
), GFP_KERNEL
);
205 adc
->pcf
= dev_to_pcf50633(pdev
->dev
.parent
);
206 platform_set_drvdata(pdev
, adc
);
208 pcf50633_register_irq(adc
->pcf
, PCF50633_IRQ_ADCRDY
,
209 pcf50633_adc_irq
, adc
);
211 mutex_init(&adc
->queue_mutex
);
216 static int pcf50633_adc_remove(struct platform_device
*pdev
)
218 struct pcf50633_adc
*adc
= platform_get_drvdata(pdev
);
221 pcf50633_free_irq(adc
->pcf
, PCF50633_IRQ_ADCRDY
);
223 mutex_lock(&adc
->queue_mutex
);
224 head
= adc
->queue_head
;
226 if (WARN_ON(adc
->queue
[head
]))
227 dev_err(adc
->pcf
->dev
,
228 "adc driver removed with request pending\n");
230 for (i
= 0; i
< PCF50633_MAX_ADC_FIFO_DEPTH
; i
++)
231 kfree(adc
->queue
[i
]);
233 mutex_unlock(&adc
->queue_mutex
);
238 static struct platform_driver pcf50633_adc_driver
= {
240 .name
= "pcf50633-adc",
242 .probe
= pcf50633_adc_probe
,
243 .remove
= pcf50633_adc_remove
,
246 module_platform_driver(pcf50633_adc_driver
);
248 MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
249 MODULE_DESCRIPTION("PCF50633 adc driver");
250 MODULE_LICENSE("GPL");
251 MODULE_ALIAS("platform:pcf50633-adc");