Thank you to anyone who has already donated - your generous donations helped make three months of treatment possible.
My brother Nate continues to fight stage IV Hodgkin's lymphoma. He's just 31, with a wife and baby girl. They have no active income (since he's been unable to return to work), no insurance, and cannot afford the treatment he needs. Nate and his family need your help. Please consider a donation, every dollar helps. Thanks.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
diff --git a/firmware/target/arm/as3525/ascodec-as3525.c b/firmware/target/arm/as3525/ascodec-as3525.c index adc9b7f..96b4b2a 100644 static unsigned char *req_data_ptr = NULL; static struct ascodec_request *req_head = NULL; static struct ascodec_request *req_tail = NULL; -#if CONFIG_CPU == AS3525 static struct wakeup adc_wkup; static struct ascodec_request as_audio_req; static int int_adc = 0; #endif /* DEBUG */ static void ascodec_read_cb(unsigned const char *data, unsigned int len); -#endif /* CONFIG_CPU == AS3525 */ static void ascodec_start_req(struct ascodec_request *req); static int ascodec_continue_req(struct ascodec_request *req, int irq_status); static void ascodec_finish_req(struct ascodec_request *req); -#if CONFIG_CPU == AS3525 void INT_AUDIO(void) { VIC_INT_EN_CLEAR = INTERRUPT_AUDIO; void INT_AUDIO(void) ascodec_async_read(AS3514_IRQ_ENRD0, 3, &as_audio_req, ascodec_read_cb); } -#endif /* CONFIG_CPU == AS3525 */ void INT_I2C_AUDIO(void) { void ascodec_init(void) int prescaler; mutex_init(&as_mtx); -#if CONFIG_CPU == AS3525 wakeup_init(&adc_wkup); -#endif /* enable clock */ CGU_PERI |= CGU_I2C_AUDIO_MASTER_CLOCK_ENABLE; void ascodec_init(void) I2C2_IMR = 0x00; /* disable interrupts */ I2C2_INT_CLR |= I2C2_RIS; /* clear interrupt status */ VIC_INT_ENABLE = INTERRUPT_I2C_AUDIO; -#if CONFIG_CPU == AS3525 /* interrupts do not work correctly on as3525v2 */ VIC_INT_ENABLE = INTERRUPT_AUDIO; -#endif /* detect if USB was connected at startup since there is no transition */ if(ascodec_read(AS3514_IRQ_ENRD0) & USB_STATUS) void ascodec_init(void) #endif IRQ_USBSTAT); +#if CONFIG_CPU == AS3525v2 + /* XIRQ = IRQ, active low reset signal, 6mA open-drain output */ + ascodec_write_pmu(0x1a, 3, 0x03); + /* Generate irq on (rtc,) adc change */ + ascodec_write(AS3514_IRQ_ENRD2, /*IRQ_RTC |*/ IRQ_ADC); +#else /* Generate irq for push-pull, active high, irq on rtc+adc change */ ascodec_write(AS3514_IRQ_ENRD2, IRQ_PUSHPULL | IRQ_HIGHACTIVE | /*IRQ_RTC |*/ IRQ_ADC); +#endif } /* returns != 0 when busy */ int ascodec_readbytes(unsigned int index, unsigned int len, unsigned char *data) return i; } -/* - * Reading AS3514_IRQ_ENRD0 clears all interrupt bits, so we cache the results - * and clear individual bits when a specific interrupt is checked: - * - we clear the ENDOFCH (end of charge) interrupt when it's read - * - we set the usb and charger presence when the status change is detected - * - * on AS3525(v1) ENRD0 is only read in an interrupt handler - * on AS3525v2 the interrupt handler doesn't work (yet), so we read the register - * synchronously. - * - To avoid race conditions all the reads to this register must be atomic. - * We don't need to disable interrupts when reading it because all the reads - * (in powermgmt-ascodec.c and power-as3525.c) are performed by the same - * thread (the power thread). - */ -static void cache_enrd0(int enrd0) +static void ascodec_read_cb(unsigned const char *data, unsigned int len) { - if (enrd0 & CHG_ENDOFCH) { /* chg finished */ + if (len != 3) /* some error happened? */ + return; + + if (data[0] & CHG_ENDOFCH) { /* chg finished */ ascodec_enrd0_shadow |= CHG_ENDOFCH; IFDEBUG(int_chg_finished++); } - if (enrd0 & CHG_CHANGED) { /* chg status changed */ - if (enrd0 & CHG_STATUS) { + if (data[0] & CHG_CHANGED) { /* chg status changed */ + if (data[0] & CHG_STATUS) { ascodec_enrd0_shadow |= CHG_STATUS; IFDEBUG(int_chg_insert++); } else { static void cache_enrd0(int enrd0) IFDEBUG(int_chg_remove++); } } - if (enrd0 & USB_CHANGED) { /* usb status changed */ - if (enrd0 & USB_STATUS) { + if (data[0] & USB_CHANGED) { /* usb status changed */ + if (data[0] & USB_STATUS) { IFDEBUG(int_usb_insert++); usb_insert_int(); } else { static void cache_enrd0(int enrd0) usb_remove_int(); } } -} - -#if CONFIG_CPU == AS3525 -static void ascodec_read_cb(unsigned const char *data, unsigned int len) -{ - if (len != 3) /* some error happened? */ - return; - - cache_enrd0(data[0]); - if (data[2] & IRQ_RTC) { /* rtc irq */ /* * Can be configured for once per second or once per minute, static void ascodec_read_cb(unsigned const char *data, unsigned int len) VIC_INT_ENABLE = INTERRUPT_AUDIO; } -#endif /* CONFIG_CPU == AS3525 */ - void ascodec_wait_adc_finished(void) { -#if CONFIG_CPU == AS3525 wakeup_wait(&adc_wkup, TIMEOUT_BLOCK); -#else - /* no interrupts, busy wait - * XXX: make sure this is the only reader of IRQ_ENRD2 - */ - while(!(ascodec_read(AS3514_IRQ_ENRD2) & IRQ_ADC)) - yield(); -#endif } #ifdef CONFIG_CHARGING bool ascodec_endofch(void) { -#if CONFIG_CPU != AS3525 - cache_enrd0(ascodec_read(AS3514_IRQ_ENRD0)); -#endif bool ret = ascodec_enrd0_shadow & CHG_ENDOFCH; ascodec_enrd0_shadow &= ~CHG_ENDOFCH; // clear interrupt return ret; bool ascodec_endofch(void) bool ascodec_chg_status(void) { -#if CONFIG_CPU != AS3525 - cache_enrd0(ascodec_read(AS3514_IRQ_ENRD0)); -#endif return ascodec_enrd0_shadow & CHG_STATUS; } #endif /* CONFIG_CHARGING */ |