summaryrefslogtreecommitdiff
path: root/firmware/target/arm/as3525/ascodec-as3525.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/as3525/ascodec-as3525.c')
-rw-r--r--firmware/target/arm/as3525/ascodec-as3525.c469
1 files changed, 109 insertions, 360 deletions
diff --git a/firmware/target/arm/as3525/ascodec-as3525.c b/firmware/target/arm/as3525/ascodec-as3525.c
index d930d266a6..ec25a415a5 100644
--- a/firmware/target/arm/as3525/ascodec-as3525.c
+++ b/firmware/target/arm/as3525/ascodec-as3525.c
@@ -24,7 +24,7 @@
24 This part is on address 0x46 of the internal i2c bus in the as3525. 24 This part is on address 0x46 of the internal i2c bus in the as3525.
25 Registers in the codec part seem to be nearly identical to the registers 25 Registers in the codec part seem to be nearly identical to the registers
26 in the AS3514 (used in the "v1" versions of the sansa c200 and e200). 26 in the AS3514 (used in the "v1" versions of the sansa c200 and e200).
27 27
28 I2C register description: 28 I2C register description:
29 * I2C2_CNTRL needs to be set to 0x51 for transfers to work at all. 29 * I2C2_CNTRL needs to be set to 0x51 for transfers to work at all.
30 bit 0: ? possibly related to using ACKs during transfers 30 bit 0: ? possibly related to using ACKs during transfers
@@ -39,7 +39,7 @@
39 * I2C2_SLAD0 contains the i2c slave address to read from / write to. 39 * I2C2_SLAD0 contains the i2c slave address to read from / write to.
40 * I2C2_CPSR0/1 is the divider from the peripheral clock to the i2c clock. 40 * I2C2_CPSR0/1 is the divider from the peripheral clock to the i2c clock.
41 * I2C2_DACNT sets the number of bytes to transfer and actually starts it. 41 * I2C2_DACNT sets the number of bytes to transfer and actually starts it.
42 42
43 When a transfer is attempted to a non-existing i2c slave address, 43 When a transfer is attempted to a non-existing i2c slave address,
44 interrupt bit 7 is raised and DACNT is not decremented after the transfer. 44 interrupt bit 7 is raised and DACNT is not decremented after the transfer.
45 */ 45 */
@@ -50,6 +50,7 @@
50#include "system.h" 50#include "system.h"
51#include "as3525.h" 51#include "as3525.h"
52#include "i2c.h" 52#include "i2c.h"
53#include "logf.h"
53 54
54#define I2C2_DATA *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x00)) 55#define I2C2_DATA *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x00))
55#define I2C2_SLAD0 *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x04)) 56#define I2C2_SLAD0 *((volatile unsigned int *)(I2C_AUDIO_BASE + 0x04))
@@ -77,223 +78,50 @@
77#define I2C2_IRQ_RXOVER 0x10 78#define I2C2_IRQ_RXOVER 0x10
78#define I2C2_IRQ_ACKTIMEO 0x80 79#define I2C2_IRQ_ACKTIMEO 0x80
79 80
80#define REQ_UNFINISHED 0
81#define REQ_FINISHED 1
82#define REQ_RETRY 2
83
84#ifdef DEBUG
85#define IFDEBUG(x) x
86#else
87#define IFDEBUG(x)
88#endif
89
90#define ASCODEC_REQ_READ 0
91#define ASCODEC_REQ_WRITE 1
92
93/*
94 * How many bytes we using in struct ascodec_request for the data buffer.
95 * 4 fits the alignment best right now.
96 * We don't actually use more than 3 at the moment (when reading interrupts)
97 * Upper limit would be 255 since DACNT is 8 bits!
98 */
99#define ASCODEC_REQ_MAXLEN 4
100
101typedef void (ascodec_cb_fn)(unsigned const char *data, unsigned cnt);
102
103struct ascodec_request {
104 unsigned char type;
105 unsigned char index;
106 unsigned char status;
107 unsigned char cnt;
108 unsigned char data[ASCODEC_REQ_MAXLEN];
109 struct semaphore complete;
110 ascodec_cb_fn *callback;
111 struct ascodec_request *next;
112};
113
114 81
115static struct mutex as_mtx; 82static struct mutex as_mtx;
116 83
117static unsigned long ascodec_enrd0_shadow = 0; 84#if CONFIG_CHARGING
118 85static bool chg_status = false;
119static unsigned char *req_data_ptr = NULL; 86static bool endofch = false;
120static struct ascodec_request *req_head = NULL; 87#endif
121static struct ascodec_request *req_tail = NULL;
122
123static struct semaphore adc_done_sem;
124static struct ascodec_request as_audio_req;
125
126#ifdef DEBUG
127static int int_audio_ctr = 0;
128static int int_chg_finished = 0;
129static int int_chg_insert = 0;
130static int int_chg_remove = 0;
131static int int_usb_insert = 0;
132static int int_usb_remove = 0;
133static int int_rtc = 0;
134static int int_adc = 0;
135#endif /* DEBUG */
136 88
137/* returns != 0 when busy */ 89/* returns true when busy */
138static inline int i2c_busy(void) 90static inline bool i2c_busy(void)
139{ 91{
140 return (I2C2_SR & 1); 92 return (I2C2_SR & 1);
141} 93}
142 94
143static void ascodec_finish_req(struct ascodec_request *req) 95void i2c_init(void)
144{
145 /*
146 * Wait if still busy, unfortunately this happens since
147 * the controller is running at a low divisor, so it's
148 * still busy when we serviced the interrupt.
149 * I tried upping the i2c speed to 4MHz which
150 * made the number of busywait cycles much smaller
151 * (none for reads and only a few for writes),
152 * but who knows if it's reliable at that frequency. ;)
153 * For one thing, 8MHz doesn't work, so 4MHz is likely
154 * borderline.
155 * In general writes need much more wait cycles than reads
156 * for some reason, possibly because we read the data register
157 * for reads, which will likely block the processor while
158 * the i2c controller responds to the register read.
159 */
160 while (i2c_busy());
161
162 req->status = 1;
163
164 if (req->callback) {
165 req->callback(req->data, req_data_ptr - req->data);
166 }
167 semaphore_release(&req->complete);
168}
169
170static int ascodec_continue_req(struct ascodec_request *req, int irq_status)
171{ 96{
172 if ((irq_status & (I2C2_IRQ_RXOVER|I2C2_IRQ_ACKTIMEO)) > 0) {
173 /* some error occured, restart the request */
174 return REQ_RETRY;
175 }
176 if (req->type == ASCODEC_REQ_READ &&
177 (irq_status & I2C2_IRQ_RXFULL) > 0) {
178 *(req_data_ptr++) = I2C2_DATA;
179 } else {
180 if (req->cnt > 1 &&
181 (irq_status & I2C2_IRQ_TXEMPTY) > 0) {
182 I2C2_DATA = *(req_data_ptr++);
183 }
184 }
185
186 req->index++;
187 if (--req->cnt > 0)
188 return REQ_UNFINISHED;
189
190 return REQ_FINISHED;
191} 97}
192 98
193static void ascodec_start_req(struct ascodec_request *req) 99static void i2c2_init(void)
194{ 100{
195 int unmask = 0; 101 int prescaler;
196
197 /* enable clock */
198 bitset32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE);
199
200 /* start transfer */
201 I2C2_SADDR = req->index;
202 if (req->type == ASCODEC_REQ_READ) {
203 req_data_ptr = req->data;
204 /* start transfer */
205 I2C2_CNTRL = I2C2_CNTRL_DEFAULT | I2C2_CNTRL_READ;
206 unmask = I2C2_IRQ_RXFULL|I2C2_IRQ_RXOVER;
207 } else {
208 req_data_ptr = &req->data[1];
209 I2C2_CNTRL = I2C2_CNTRL_DEFAULT | I2C2_CNTRL_WRITE;
210 I2C2_DATA = req->data[0];
211 unmask = I2C2_IRQ_TXEMPTY|I2C2_IRQ_ACKTIMEO;
212 }
213
214 I2C2_DACNT = req->cnt;
215 I2C2_IMR |= unmask; /* enable interrupts */
216}
217
218void INT_I2C_AUDIO(void)
219{
220 struct ascodec_request *req = req_head;
221
222 int irq_status = I2C2_MIS;
223 int status = ascodec_continue_req(req, irq_status);
224
225 I2C2_INT_CLR = irq_status; /* clear interrupt status */
226
227 if (status != REQ_UNFINISHED) {
228 /* mask rx/tx interrupts */
229 I2C2_IMR &= ~(I2C2_IRQ_TXEMPTY|I2C2_IRQ_RXFULL|
230 I2C2_IRQ_RXOVER|I2C2_IRQ_ACKTIMEO);
231
232 if (status == REQ_FINISHED)
233 ascodec_finish_req(req);
234
235 int oldlevel = disable_irq_save(); /* IRQs are stacked */
236
237 /*
238 * If status == REQ_RETRY, this will restart
239 * the request because we didn't remove it from
240 * the request list
241 */
242
243 if (status == REQ_FINISHED) {
244 req_head = req->next;
245 req->next = NULL;
246 }
247 102
248 if (req_head == NULL) { 103 /* prescaler for i2c clock */
249 req_tail = NULL; 104 prescaler = AS3525_I2C_PRESCALER;
105 I2C2_CPSR0 = prescaler & 0xFF; /* 8 lsb */
106 I2C2_CPSR1 = (prescaler >> 8) & 0x3; /* 2 msb */
250 107
251 /* disable clock */ 108 /* set i2c slave address of codec part */
252 bitclr32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE); 109 I2C2_SLAD0 = AS3514_I2C_ADDR << 1;
253 } else {
254 ascodec_start_req(req_head);
255 }
256 110
257 restore_irq(oldlevel); 111 I2C2_CNTRL = I2C2_CNTRL_DEFAULT;
258 }
259}
260 112
261void i2c_init(void)
262{
263} 113}
264 114
265/* initialises the internal i2c bus and prepares for transfers to the codec */ 115/* initialises the internal i2c bus and prepares for transfers to the codec */
266void ascodec_init(void) 116void ascodec_init(void)
267{ 117{
268 int prescaler;
269 118
270 mutex_init(&as_mtx); 119 mutex_init(&as_mtx);
271 semaphore_init(&adc_done_sem, 1, 0);
272 120
273 /* enable clock */ 121 /* enable clock */
274 bitset32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE); 122 bitset32(&CGU_PERI, CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE);
275 123
276 /* prescaler for i2c clock */ 124 i2c2_init();
277 prescaler = AS3525_I2C_PRESCALER;
278 I2C2_CPSR0 = prescaler & 0xFF; /* 8 lsb */
279 I2C2_CPSR1 = (prescaler >> 8) & 0x3; /* 2 msb */
280
281 /* set i2c slave address of codec part */
282 I2C2_SLAD0 = AS3514_I2C_ADDR << 1;
283
284 I2C2_CNTRL = I2C2_CNTRL_DEFAULT;
285
286 I2C2_IMR = 0x00; /* disable interrupts */
287 I2C2_INT_CLR = I2C2_RIS; /* clear interrupt status */
288 VIC_INT_ENABLE = INTERRUPT_I2C_AUDIO;
289 VIC_INT_ENABLE = INTERRUPT_AUDIO;
290
291 /* detect if USB was connected at startup since there is no transition */
292 ascodec_enrd0_shadow = ascodec_read(AS3514_IRQ_ENRD0);
293 if(ascodec_enrd0_shadow & USB_STATUS)
294 usb_insert_int();
295 else
296 usb_remove_int();
297 125
298 /* Generate irq for usb+charge status change */ 126 /* Generate irq for usb+charge status change */
299 ascodec_write(AS3514_IRQ_ENRD0, 127 ascodec_write(AS3514_IRQ_ENRD0,
@@ -305,242 +133,172 @@ void ascodec_init(void)
305#if CONFIG_CPU == AS3525v2 133#if CONFIG_CPU == AS3525v2
306 /* XIRQ = IRQ, active low reset signal, 6mA push-pull output */ 134 /* XIRQ = IRQ, active low reset signal, 6mA push-pull output */
307 ascodec_write_pmu(0x1a, 3, (1<<2)|3); /* 1A-3 = Out_Cntr3 register */ 135 ascodec_write_pmu(0x1a, 3, (1<<2)|3); /* 1A-3 = Out_Cntr3 register */
308 /* Generate irq on (rtc,) adc change */ 136 /* reset for compatible with old bootloader */
309 ascodec_write(AS3514_IRQ_ENRD2, /*IRQ_RTC |*/ IRQ_ADC); 137 ascodec_write(AS3514_IRQ_ENRD2, 0x0);
310#else 138#else
311 /* Generate irq for push-pull, active high, irq on rtc+adc change */ 139 /* Generate irq for push-pull, active high, irq on rtc+adc change */
312 ascodec_write(AS3514_IRQ_ENRD2, IRQ_PUSHPULL | IRQ_HIGHACTIVE | 140 ascodec_write(AS3514_IRQ_ENRD2, IRQ_PUSHPULL | IRQ_HIGHACTIVE);
313 /*IRQ_RTC |*/ IRQ_ADC);
314#endif 141#endif
315}
316 142
317static void ascodec_req_init(struct ascodec_request *req, int type, 143 VIC_INT_ENABLE = INTERRUPT_AUDIO;
318 unsigned int index, unsigned int cnt) 144
319{ 145 /* detect if USB was connected at startup since there is no transition */
320 semaphore_init(&req->complete, 1, 0); 146 int data = ascodec_read(AS3514_IRQ_ENRD0);
321 req->next = NULL; 147
322 req->callback = NULL; 148 if(data & USB_STATUS)
323 req->type = type; 149 usb_insert_int();
324 req->index = index; 150
325 req->cnt = cnt; 151#if CONFIG_CHARGING
152 chg_status = data & CHG_STATUS;
153#endif
326} 154}
327 155
328static void ascodec_submit(struct ascodec_request *req) 156/* returns false if transfer incomplete */
157static bool i2c2_transfer(void)
329{ 158{
330 int oldlevel = disable_irq_save(); 159 static int try = 0;
331 160
332 req->status = 0; 161 /* wait for transfer*/
162 int i = 10000;
163 while (I2C2_DACNT != 0 && i--);
333 164
334 if (req_head == NULL) { 165 if (!i) {
335 req_tail = req_head = req; 166 if (try == 5)
336 ascodec_start_req(req); 167 panicf("I2C2 reset failed");
337 } else {
338 req_tail->next = req;
339 req_tail = req;
340 }
341 168
342 restore_irq(oldlevel); 169 logf("reset I2C2 %d", try);
343}
344 170
345static void ascodec_wait(struct ascodec_request *req) 171 i2c2_init();
346{
347 /* NOTE: Only safe from thread context */
348 172
349 if (irq_enabled()) { 173 try++;
350 semaphore_wait(&req->complete, TIMEOUT_BLOCK); 174 return false;
351 return;
352 } 175 }
353 176
354 while (req->status == 0) { 177 try = 0;
355 if (I2C2_MIS) INT_I2C_AUDIO(); 178 return true;
356 }
357} 179}
358 180
359/* 181void ascodec_write(unsigned int index, unsigned int value)
360 * The request struct passed in must be allocated statically.
361 * If you call ascodec_async_write from different places, each
362 * call needs it's own request struct.
363 */
364static void ascodec_async_write(unsigned int index, unsigned int value,
365 struct ascodec_request *req)
366{ 182{
183 ascodec_lock();
184
367#ifndef HAVE_AS3543 185#ifndef HAVE_AS3543
368 if (index == AS3514_CVDD_DCDC3) /* prevent setting of the LREG_CP_not bit */ 186 if (index == AS3514_CVDD_DCDC3) /* prevent setting of the LREG_CP_not bit */
369 value &= ~(1 << 5); 187 value &= ~(1 << 5);
370#endif 188#endif
371 189
372 ascodec_req_init(req, ASCODEC_REQ_WRITE, index, 1); 190 do {
373 req->data[0] = value; 191 /* wait if still busy */
374 ascodec_submit(req); 192 while (i2c_busy());
375}
376 193
377/* returns 0 on success, <0 otherwise */ 194 /* start transfer */
378int ascodec_write(unsigned int index, unsigned int value) 195 I2C2_SADDR = index;
379{ 196 I2C2_CNTRL &= ~(1 << 1);
380 struct ascodec_request req; 197 I2C2_DATA = value;
198 I2C2_DACNT = 1;
381 199
382 ascodec_async_write(index, value, &req); 200 } while (!i2c2_transfer());
383 ascodec_wait(&req);
384 201
385 return 0; 202 ascodec_unlock();
386} 203}
387 204
388/*
389 * The request struct passed in must be allocated statically.
390 * If you call ascodec_async_read from different places, each
391 * call needs it's own request struct.
392 * If len is bigger than ASCODEC_REQ_MAXLEN it will be
393 * set to ASCODEC_REQ_MAXLEN.
394 */
395static void ascodec_async_read(unsigned int index, unsigned int len,
396 struct ascodec_request *req, ascodec_cb_fn *cb)
397{
398 if (len > ASCODEC_REQ_MAXLEN)
399 len = ASCODEC_REQ_MAXLEN; /* can't fit more in one request */
400
401 ascodec_req_init(req, ASCODEC_REQ_READ, index, len);
402 req->callback = cb;
403 ascodec_submit(req);
404}
405
406/* returns value read on success, <0 otherwise */
407int ascodec_read(unsigned int index) 205int ascodec_read(unsigned int index)
408{ 206{
409 struct ascodec_request req; 207 int data;
410
411 ascodec_async_read(index, 1, &req, NULL);
412 ascodec_wait(&req);
413 208
414 return req.data[0]; 209 ascodec_lock();
415}
416 210
417int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data) 211 do {
418{ 212 /* wait if still busy */
419 int i, j; 213 while (i2c_busy());
420 struct ascodec_request req;
421 214
422 /* index and cnt will be filled in later, just use 0 */ 215 /* start transfer */
423 ascodec_req_init(&req, ASCODEC_REQ_READ, 0, 0); 216 I2C2_SADDR = index;
217 I2C2_CNTRL |= (1 << 1);
218 I2C2_DACNT = 1;
424 219
425 i = 0; 220 } while (!i2c2_transfer());
426 while (len > 0) {
427 int cnt = len > ASCODEC_REQ_MAXLEN ? ASCODEC_REQ_MAXLEN : len;
428 221
429 req.index = index; 222 data = I2C2_DATA;
430 req.cnt = cnt;
431 223
432 ascodec_submit(&req); 224 ascodec_unlock();
433 ascodec_wait(&req);
434 225
435 for (j=0; j<cnt; j++) data[i++] = req.data[j]; 226 return data;
227}
436 228
437 len -= cnt; 229void ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data)
438 index += cnt; 230{
439 } 231 unsigned int i;
440 232
441 return i; 233 for(i = 0; i < len; i++)
234 data[i] = ascodec_read(index+i);
442} 235}
443 236
444#if CONFIG_CPU == AS3525v2 237#if CONFIG_CPU == AS3525v2
445void ascodec_write_pmu(unsigned int index, unsigned int subreg, 238void ascodec_write_pmu(unsigned int index, unsigned int subreg,
446 unsigned int value) 239 unsigned int value)
447{ 240{
448 struct ascodec_request reqs[2]; 241 ascodec_lock();
449
450 int oldstatus = disable_irq_save();
451 /* we submit consecutive requests to make sure no operations happen on the 242 /* we submit consecutive requests to make sure no operations happen on the
452 * i2c bus between selecting the sub register and writing to it */ 243 * i2c bus between selecting the sub register and writing to it */
453 ascodec_async_write(AS3543_PMU_ENABLE, 8 | subreg, &reqs[0]); 244 ascodec_write(AS3543_PMU_ENABLE, 8 | subreg);
454 ascodec_async_write(index, value, &reqs[1]); 245 ascodec_write(index, value);
455 restore_irq(oldstatus);
456 246
457 /* Wait for second request to finish */ 247 ascodec_unlock();
458 ascodec_wait(&reqs[1]);
459} 248}
460 249
461int ascodec_read_pmu(unsigned int index, unsigned int subreg) 250int ascodec_read_pmu(unsigned int index, unsigned int subreg)
462{ 251{
463 struct ascodec_request reqs[2]; 252 ascodec_lock();
464
465 int oldstatus = disable_irq_save();
466 /* we submit consecutive requests to make sure no operations happen on the 253 /* we submit consecutive requests to make sure no operations happen on the
467 * i2c bus between selecting the sub register and reading it */ 254 * i2c bus between selecting the sub register and reading it */
468 ascodec_async_write(AS3543_PMU_ENABLE, subreg, &reqs[0]); 255 ascodec_write(AS3543_PMU_ENABLE, subreg);
469 ascodec_async_read(index, 1, &reqs[1], NULL); 256 int ret = ascodec_read(index);
470 restore_irq(oldstatus);
471 257
472 /* Wait for second request to finish */ 258 ascodec_unlock();
473 ascodec_wait(&reqs[1]);
474 259
475 return reqs[1].data[0]; 260 return ret;
476} 261}
477#endif /* CONFIG_CPU == AS3525v2 */ 262#endif /* CONFIG_CPU == AS3525v2 */
478 263
479static void ascodec_read_cb(unsigned const char *data, unsigned int len) 264void INT_AUDIO(void)
480{ 265{
481 if (UNLIKELY(len != 3)) /* some error happened? */ 266 int oldstatus = disable_irq_save();
482 panicf("INT_AUDIO callback got %d regs", len); 267 int data = ascodec_read(AS3514_IRQ_ENRD0);
483 268
484 if (data[0] & CHG_ENDOFCH) { /* chg finished */ 269#if CONFIG_CHARGING
485 ascodec_enrd0_shadow |= CHG_ENDOFCH; 270 if (data & CHG_ENDOFCH) { /* chg finished */
486 IFDEBUG(int_chg_finished++); 271 endofch = true;
487 }
488 if (data[0] & CHG_CHANGED) { /* chg status changed */
489 if (data[0] & CHG_STATUS) {
490 ascodec_enrd0_shadow |= CHG_STATUS;
491 IFDEBUG(int_chg_insert++);
492 } else {
493 ascodec_enrd0_shadow &= ~CHG_STATUS;
494 IFDEBUG(int_chg_remove++);
495 }
496 } 272 }
497 if (data[0] & USB_CHANGED) { /* usb status changed */ 273
498 if (data[0] & USB_STATUS) { 274 chg_status = data & CHG_STATUS;
499 IFDEBUG(int_usb_insert++); 275#endif
276
277 if (data & USB_CHANGED) { /* usb status changed */
278 if (data & USB_STATUS) {
500 usb_insert_int(); 279 usb_insert_int();
501 } else { 280 } else {
502 IFDEBUG(int_usb_remove++);
503 usb_remove_int(); 281 usb_remove_int();
504 } 282 }
505 } 283 }
506 if (data[2] & IRQ_RTC) { /* rtc irq */
507 /*
508 * Can be configured for once per second or once per minute,
509 * default is once per second
510 */
511 IFDEBUG(int_rtc++);
512 }
513 if (data[2] & IRQ_ADC) { /* adc finished */
514 IFDEBUG(int_adc++);
515 semaphore_release(&adc_done_sem);
516 }
517 VIC_INT_ENABLE = INTERRUPT_AUDIO;
518}
519 284
520void INT_AUDIO(void) 285 restore_irq(oldstatus);
521{
522 VIC_INT_EN_CLEAR = INTERRUPT_AUDIO;
523 IFDEBUG(int_audio_ctr++);
524
525 ascodec_async_read(AS3514_IRQ_ENRD0, 3, &as_audio_req, ascodec_read_cb);
526}
527
528void ascodec_wait_adc_finished(void)
529{
530 semaphore_wait(&adc_done_sem, TIMEOUT_BLOCK);
531} 286}
532 287
533#if CONFIG_CHARGING 288#if CONFIG_CHARGING
534bool ascodec_endofch(void) 289bool ascodec_endofch(void)
535{ 290{
536 bool ret = ascodec_enrd0_shadow & CHG_ENDOFCH; 291 int oldstatus = disable_irq_save();
537 bitclr32(&ascodec_enrd0_shadow, CHG_ENDOFCH); /* clear interrupt */ 292 bool ret = endofch;
293 endofch = false;
294 restore_irq(oldstatus);
295
538 return ret; 296 return ret;
539} 297}
540 298
541bool ascodec_chg_status(void) 299bool ascodec_chg_status(void)
542{ 300{
543 return ascodec_enrd0_shadow & CHG_STATUS; 301 return chg_status;
544} 302}
545 303
546void ascodec_monitor_endofch(void) 304void ascodec_monitor_endofch(void)
@@ -567,15 +325,6 @@ int ascodec_read_charger(void)
567} 325}
568#endif /* CONFIG_CHARGING */ 326#endif /* CONFIG_CHARGING */
569 327
570/*
571 * NOTE:
572 * After the conversion to interrupts, ascodec_(lock|unlock) are only used by
573 * adc-as3514.c to protect against other threads corrupting the result by using
574 * the ADC at the same time.
575 * Concurrent ascodec_(async_)?(read|write) calls are instead protected
576 * because ascodec_submit() is atomic and concurrent requests will wait
577 * in the queue until the current request is finished.
578 */
579void ascodec_lock(void) 328void ascodec_lock(void)
580{ 329{
581 mutex_lock(&as_mtx); 330 mutex_lock(&as_mtx);