Branch data Line data Source code
1 : : /* ==========================================================================
2 : : * $File: //dwh/usb_iip/dev/software/otg/linux/drivers/dwc_otg_hcd_intr.c $
3 : : * $Revision: #89 $
4 : : * $Date: 2011/10/20 $
5 : : * $Change: 1869487 $
6 : : *
7 : : * Synopsys HS OTG Linux Software Driver and documentation (hereinafter,
8 : : * "Software") is an Unsupported proprietary work of Synopsys, Inc. unless
9 : : * otherwise expressly agreed to in writing between Synopsys and you.
10 : : *
11 : : * The Software IS NOT an item of Licensed Software or Licensed Product under
12 : : * any End User Software License Agreement or Agreement for Licensed Product
13 : : * with Synopsys or any supplement thereto. You are permitted to use and
14 : : * redistribute this Software in source and binary forms, with or without
15 : : * modification, provided that redistributions of source code must retain this
16 : : * notice. You may not view, use, disclose, copy or distribute this file or
17 : : * any information contained herein except pursuant to this license grant from
18 : : * Synopsys. If you do not agree with this notice, including the disclaimer
19 : : * below, then you are not authorized to use the Software.
20 : : *
21 : : * THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS" BASIS
22 : : * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : : * ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS BE LIABLE FOR ANY DIRECT,
25 : : * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 : : * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 : : * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28 : : * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 : : * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 : : * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
31 : : * DAMAGE.
32 : : * ========================================================================== */
33 : : #ifndef DWC_DEVICE_ONLY
34 : :
35 : : #include "dwc_otg_hcd.h"
36 : : #include "dwc_otg_regs.h"
37 : :
38 : : #include <linux/jiffies.h>
39 : : #ifdef CONFIG_ARM
40 : : #include <asm/fiq.h>
41 : : #endif
42 : :
43 : : extern bool microframe_schedule;
44 : :
45 : : /** @file
46 : : * This file contains the implementation of the HCD Interrupt handlers.
47 : : */
48 : :
49 : : int fiq_done, int_done;
50 : :
51 : : #ifdef FIQ_DEBUG
52 : : char buffer[1000*16];
53 : : int wptr;
54 : : void notrace _fiq_print(FIQDBG_T dbg_lvl, char *fmt, ...)
55 : : {
56 : : FIQDBG_T dbg_lvl_req = FIQDBG_PORTHUB;
57 : : va_list args;
58 : : char text[17];
59 : : hfnum_data_t hfnum = { .d32 = FIQ_READ(dwc_regs_base + 0x408) };
60 : :
61 : : if(dbg_lvl & dbg_lvl_req || dbg_lvl == FIQDBG_ERR)
62 : : {
63 : : local_fiq_disable();
64 : : snprintf(text, 9, "%4d%d:%d ", hfnum.b.frnum/8, hfnum.b.frnum%8, 8 - hfnum.b.frrem/937);
65 : : va_start(args, fmt);
66 : : vsnprintf(text+8, 9, fmt, args);
67 : : va_end(args);
68 : :
69 : : memcpy(buffer + wptr, text, 16);
70 : : wptr = (wptr + 16) % sizeof(buffer);
71 : : local_fiq_enable();
72 : : }
73 : : }
74 : : #endif
75 : :
76 : : /** This function handles interrupts for the HCD. */
77 : 13798838 : int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
78 : : {
79 : : int retval = 0;
80 : : static int last_time;
81 : 13798838 : dwc_otg_core_if_t *core_if = dwc_otg_hcd->core_if;
82 : : gintsts_data_t gintsts;
83 : : gintmsk_data_t gintmsk;
84 : : hfnum_data_t hfnum;
85 : : haintmsk_data_t haintmsk;
86 : :
87 : : #ifdef DEBUG
88 : : dwc_otg_core_global_regs_t *global_regs = core_if->core_global_regs;
89 : :
90 : : #endif
91 : :
92 : 13798838 : gintsts.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintsts);
93 : 13798838 : gintmsk.d32 = DWC_READ_REG32(&core_if->core_global_regs->gintmsk);
94 : :
95 : : /* Exit from ISR if core is hibernated */
96 [ + - ]: 13798838 : if (core_if->hibernation_suspend == 1) {
97 : : goto exit_handler_routine;
98 : : }
99 : 13798838 : DWC_SPINLOCK(dwc_otg_hcd->lock);
100 : : /* Check if HOST Mode */
101 [ + - ]: 13798838 : if (dwc_otg_is_host_mode(core_if)) {
102 [ + - ]: 13798838 : if (fiq_enable) {
103 : 13798838 : local_fiq_disable();
104 : 13798838 : fiq_fsm_spin_lock(&dwc_otg_hcd->fiq_state->lock);
105 : : /* Pull in from the FIQ's disabled mask */
106 : 13798838 : gintmsk.d32 = gintmsk.d32 | ~(dwc_otg_hcd->fiq_state->gintmsk_saved.d32);
107 : 13798838 : dwc_otg_hcd->fiq_state->gintmsk_saved.d32 = ~0;
108 : : }
109 : :
110 [ + - + + ]: 13798838 : if (fiq_fsm_enable && ( 0x0000FFFF & ~(dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint))) {
111 : 6811787 : gintsts.b.hcintr = 1;
112 : : }
113 : :
114 : : /* Danger will robinson: fake a SOF if necessary */
115 [ + - + - ]: 13798838 : if (fiq_fsm_enable && (dwc_otg_hcd->fiq_state->gintmsk_saved.b.sofintr == 1)) {
116 : 13798838 : gintsts.b.sofintr = 1;
117 : : }
118 : 13798838 : gintsts.d32 &= gintmsk.d32;
119 : :
120 [ + - ]: 13798838 : if (fiq_enable) {
121 : 13798838 : fiq_fsm_spin_unlock(&dwc_otg_hcd->fiq_state->lock);
122 : 13798838 : local_fiq_enable();
123 : : }
124 : :
125 [ + - ]: 13798838 : if (!gintsts.d32) {
126 : : goto exit_handler_routine;
127 : : }
128 : :
129 : : #ifdef DEBUG
130 : : // We should be OK doing this because the common interrupts should already have been serviced
131 : : /* Don't print debug message in the interrupt handler on SOF */
132 : : #ifndef DEBUG_SOF
133 : : if (gintsts.d32 != DWC_SOF_INTR_MASK)
134 : : #endif
135 : : DWC_DEBUGPL(DBG_HCDI, "\n");
136 : : #endif
137 : :
138 : : #ifdef DEBUG
139 : : #ifndef DEBUG_SOF
140 : : if (gintsts.d32 != DWC_SOF_INTR_MASK)
141 : : #endif
142 : : DWC_DEBUGPL(DBG_HCDI,
143 : : "DWC OTG HCD Interrupt Detected gintsts&gintmsk=0x%08x core_if=%p\n",
144 : : gintsts.d32, core_if);
145 : : #endif
146 : 13798838 : hfnum.d32 = DWC_READ_REG32(&dwc_otg_hcd->core_if->host_if->host_global_regs->hfnum);
147 [ + - ]: 13798838 : if (gintsts.b.sofintr) {
148 : 13798838 : retval |= dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd);
149 : : }
150 : :
151 [ - + ]: 13798838 : if (gintsts.b.rxstsqlvl) {
152 : 0 : retval |=
153 : 0 : dwc_otg_hcd_handle_rx_status_q_level_intr
154 : : (dwc_otg_hcd);
155 : : }
156 [ - + ]: 13798838 : if (gintsts.b.nptxfempty) {
157 : 0 : retval |=
158 : : dwc_otg_hcd_handle_np_tx_fifo_empty_intr
159 : : (dwc_otg_hcd);
160 : : }
161 : : if (gintsts.b.i2cintr) {
162 : : /** @todo Implement i2cintr handler. */
163 : : }
164 [ + + ]: 13798838 : if (gintsts.b.portintr) {
165 : :
166 : 828 : gintmsk_data_t gintmsk = { .b.portintr = 1};
167 : 828 : retval |= dwc_otg_hcd_handle_port_intr(dwc_otg_hcd);
168 [ + - ]: 828 : if (fiq_enable) {
169 : 828 : local_fiq_disable();
170 : 828 : fiq_fsm_spin_lock(&dwc_otg_hcd->fiq_state->lock);
171 : 828 : DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
172 : 828 : fiq_fsm_spin_unlock(&dwc_otg_hcd->fiq_state->lock);
173 : 828 : local_fiq_enable();
174 : : } else {
175 : 0 : DWC_MODIFY_REG32(&dwc_otg_hcd->core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
176 : : }
177 : : }
178 [ + + ]: 13798838 : if (gintsts.b.hcintr) {
179 : 6811838 : retval |= dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd);
180 : : }
181 [ - + ]: 13798838 : if (gintsts.b.ptxfempty) {
182 : 0 : retval |=
183 : : dwc_otg_hcd_handle_perio_tx_fifo_empty_intr
184 : : (dwc_otg_hcd);
185 : : }
186 : : #ifdef DEBUG
187 : : #ifndef DEBUG_SOF
188 : : if (gintsts.d32 != DWC_SOF_INTR_MASK)
189 : : #endif
190 : : {
191 : : DWC_DEBUGPL(DBG_HCDI,
192 : : "DWC OTG HCD Finished Servicing Interrupts\n");
193 : : DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintsts=0x%08x\n",
194 : : DWC_READ_REG32(&global_regs->gintsts));
195 : : DWC_DEBUGPL(DBG_HCDV, "DWC OTG HCD gintmsk=0x%08x\n",
196 : : DWC_READ_REG32(&global_regs->gintmsk));
197 : : }
198 : : #endif
199 : :
200 : : #ifdef DEBUG
201 : : #ifndef DEBUG_SOF
202 : : if (gintsts.d32 != DWC_SOF_INTR_MASK)
203 : : #endif
204 : : DWC_DEBUGPL(DBG_HCDI, "\n");
205 : : #endif
206 : :
207 : : }
208 : :
209 : : exit_handler_routine:
210 [ + - ]: 13798838 : if (fiq_enable) {
211 : : gintmsk_data_t gintmsk_new;
212 : : haintmsk_data_t haintmsk_new;
213 : 13798838 : local_fiq_disable();
214 : 13798838 : fiq_fsm_spin_lock(&dwc_otg_hcd->fiq_state->lock);
215 : 13798838 : gintmsk_new.d32 = *(volatile uint32_t *)&dwc_otg_hcd->fiq_state->gintmsk_saved.d32;
216 [ + - ]: 13798838 : if(fiq_fsm_enable)
217 : 13798838 : haintmsk_new.d32 = *(volatile uint32_t *)&dwc_otg_hcd->fiq_state->haintmsk_saved.d32;
218 : : else
219 : : haintmsk_new.d32 = 0x0000FFFF;
220 : :
221 : : /* The FIQ could have sneaked another interrupt in. If so, don't clear MPHI */
222 [ + + + + ]: 13798838 : if ((gintmsk_new.d32 == ~0) && (haintmsk_new.d32 == 0x0000FFFF)) {
223 [ - + ]: 13768734 : if (dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr) {
224 : 0 : DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr, 1);
225 : : } else {
226 : 13768734 : DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.intstat, (1<<16));
227 : : }
228 [ + + ]: 13768734 : if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) {
229 : : fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR");
230 : 281510 : DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, ((1<<31) + (1<<16)));
231 [ - + ]: 281510 : while (!(DWC_READ_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & (1 << 17)))
232 : : ;
233 : 281510 : DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, (1<<31));
234 : 281510 : dwc_otg_hcd->fiq_state->mphi_int_count = 0;
235 : : }
236 : 13768734 : int_done++;
237 : : }
238 : 13798838 : haintmsk.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
239 : : /* Re-enable interrupts that the FIQ masked (first time round) */
240 : 13798838 : FIQ_WRITE(dwc_otg_hcd->fiq_state->dwc_regs_base + GINTMSK, gintmsk.d32);
241 : 13798838 : fiq_fsm_spin_unlock(&dwc_otg_hcd->fiq_state->lock);
242 : 13798838 : local_fiq_enable();
243 : :
244 [ + + ]: 13798838 : if ((jiffies / HZ) > last_time) {
245 : : //dwc_otg_qh_t *qh;
246 : : //dwc_list_link_t *cur;
247 : : /* Once a second output the fiq and irq numbers, useful for debug */
248 : 22529 : last_time = jiffies / HZ;
249 : : // DWC_WARN("np_kick=%d AHC=%d sched_frame=%d cur_frame=%d int_done=%d fiq_done=%d",
250 : : // dwc_otg_hcd->fiq_state->kick_np_queues, dwc_otg_hcd->available_host_channels,
251 : : // dwc_otg_hcd->fiq_state->next_sched_frame, hfnum.b.frnum, int_done, dwc_otg_hcd->fiq_state->fiq_done);
252 : : //printk(KERN_WARNING "Periodic queues:\n");
253 : : }
254 : : }
255 : :
256 : 13798838 : DWC_SPINUNLOCK(dwc_otg_hcd->lock);
257 : 13798838 : return retval;
258 : : }
259 : :
260 : : #ifdef DWC_TRACK_MISSED_SOFS
261 : :
262 : : #warning Compiling code to track missed SOFs
263 : : #define FRAME_NUM_ARRAY_SIZE 1000
264 : : /**
265 : : * This function is for debug only.
266 : : */
267 : : static inline void track_missed_sofs(uint16_t curr_frame_number)
268 : : {
269 : : static uint16_t frame_num_array[FRAME_NUM_ARRAY_SIZE];
270 : : static uint16_t last_frame_num_array[FRAME_NUM_ARRAY_SIZE];
271 : : static int frame_num_idx = 0;
272 : : static uint16_t last_frame_num = DWC_HFNUM_MAX_FRNUM;
273 : : static int dumped_frame_num_array = 0;
274 : :
275 : : if (frame_num_idx < FRAME_NUM_ARRAY_SIZE) {
276 : : if (((last_frame_num + 1) & DWC_HFNUM_MAX_FRNUM) !=
277 : : curr_frame_number) {
278 : : frame_num_array[frame_num_idx] = curr_frame_number;
279 : : last_frame_num_array[frame_num_idx++] = last_frame_num;
280 : : }
281 : : } else if (!dumped_frame_num_array) {
282 : : int i;
283 : : DWC_PRINTF("Frame Last Frame\n");
284 : : DWC_PRINTF("----- ----------\n");
285 : : for (i = 0; i < FRAME_NUM_ARRAY_SIZE; i++) {
286 : : DWC_PRINTF("0x%04x 0x%04x\n",
287 : : frame_num_array[i], last_frame_num_array[i]);
288 : : }
289 : : dumped_frame_num_array = 1;
290 : : }
291 : : last_frame_num = curr_frame_number;
292 : : }
293 : : #endif
294 : :
295 : : /**
296 : : * Handles the start-of-frame interrupt in host mode. Non-periodic
297 : : * transactions may be queued to the DWC_otg controller for the current
298 : : * (micro)frame. Periodic transactions may be queued to the controller for the
299 : : * next (micro)frame.
300 : : */
301 : 13798837 : int32_t dwc_otg_hcd_handle_sof_intr(dwc_otg_hcd_t * hcd)
302 : : {
303 : : hfnum_data_t hfnum;
304 : 13798837 : gintsts_data_t gintsts = { .d32 = 0 };
305 : : dwc_list_link_t *qh_entry;
306 : : dwc_otg_qh_t *qh;
307 : : dwc_otg_transaction_type_e tr_type;
308 : : int did_something = 0;
309 : : int32_t next_sched_frame = -1;
310 : :
311 : 13798837 : hfnum.d32 =
312 : 13798837 : DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
313 : :
314 : : #ifdef DEBUG_SOF
315 : : DWC_DEBUGPL(DBG_HCD, "--Start of Frame Interrupt--\n");
316 : : #endif
317 : 13798837 : hcd->frame_number = hfnum.b.frnum;
318 : :
319 : : #ifdef DEBUG
320 : : hcd->frrem_accum += hfnum.b.frrem;
321 : : hcd->frrem_samples++;
322 : : #endif
323 : :
324 : : #ifdef DWC_TRACK_MISSED_SOFS
325 : : track_missed_sofs(hcd->frame_number);
326 : : #endif
327 : : /* Determine whether any periodic QHs should be executed. */
328 : 13798837 : qh_entry = DWC_LIST_FIRST(&hcd->periodic_sched_inactive);
329 [ + + ]: 83206274 : while (qh_entry != &hcd->periodic_sched_inactive) {
330 : : qh = DWC_LIST_ENTRY(qh_entry, dwc_otg_qh_t, qh_list_entry);
331 : 55608600 : qh_entry = qh_entry->next;
332 [ + + ]: 111217200 : if (dwc_frame_num_le(qh->sched_frame, hcd->frame_number)) {
333 : :
334 : : /*
335 : : * Move QH to the ready list to be executed next
336 : : * (micro)frame.
337 : : */
338 : 6743210 : DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_ready,
339 : : &qh->qh_list_entry);
340 : :
341 : : did_something = 1;
342 : : }
343 : : else
344 : : {
345 [ + + + + ]: 84846755 : if(next_sched_frame < 0 || dwc_frame_num_le(qh->sched_frame, next_sched_frame))
346 : : {
347 : : next_sched_frame = qh->sched_frame;
348 : : }
349 : : }
350 : : }
351 [ + - ]: 13798837 : if (fiq_enable)
352 : 13798837 : hcd->fiq_state->next_sched_frame = next_sched_frame;
353 : :
354 : 13798837 : tr_type = dwc_otg_hcd_select_transactions(hcd);
355 [ + + ]: 13798837 : if (tr_type != DWC_OTG_TRANSACTION_NONE) {
356 : 12196192 : dwc_otg_hcd_queue_transactions(hcd, tr_type);
357 : : did_something = 1;
358 : : }
359 : :
360 : : /* Clear interrupt - but do not trample on the FIQ sof */
361 [ - + ]: 13798836 : if (!fiq_fsm_enable) {
362 : 0 : gintsts.b.sofintr = 1;
363 : 0 : DWC_WRITE_REG32(&hcd->core_if->core_global_regs->gintsts, gintsts.d32);
364 : : }
365 : 13798836 : return 1;
366 : : }
367 : :
368 : : /** Handles the Rx Status Queue Level Interrupt, which indicates that there is at
369 : : * least one packet in the Rx FIFO. The packets are moved from the FIFO to
370 : : * memory if the DWC_otg controller is operating in Slave mode. */
371 : 0 : int32_t dwc_otg_hcd_handle_rx_status_q_level_intr(dwc_otg_hcd_t * dwc_otg_hcd)
372 : : {
373 : : host_grxsts_data_t grxsts;
374 : : dwc_hc_t *hc = NULL;
375 : :
376 : : DWC_DEBUGPL(DBG_HCD, "--RxStsQ Level Interrupt--\n");
377 : :
378 : 0 : grxsts.d32 =
379 : 0 : DWC_READ_REG32(&dwc_otg_hcd->core_if->core_global_regs->grxstsp);
380 : :
381 : 0 : hc = dwc_otg_hcd->hc_ptr_array[grxsts.b.chnum];
382 [ # # ]: 0 : if (!hc) {
383 : 0 : DWC_ERROR("Unable to get corresponding channel\n");
384 : 0 : return 0;
385 : : }
386 : :
387 : : /* Packet Status */
388 : : DWC_DEBUGPL(DBG_HCDV, " Ch num = %d\n", grxsts.b.chnum);
389 : : DWC_DEBUGPL(DBG_HCDV, " Count = %d\n", grxsts.b.bcnt);
390 : : DWC_DEBUGPL(DBG_HCDV, " DPID = %d, hc.dpid = %d\n", grxsts.b.dpid,
391 : : hc->data_pid_start);
392 : : DWC_DEBUGPL(DBG_HCDV, " PStatus = %d\n", grxsts.b.pktsts);
393 : :
394 [ # # # ]: 0 : switch (grxsts.b.pktsts) {
395 : : case DWC_GRXSTS_PKTSTS_IN:
396 : : /* Read the data into the host buffer. */
397 [ # # ]: 0 : if (grxsts.b.bcnt > 0) {
398 : 0 : dwc_otg_read_packet(dwc_otg_hcd->core_if,
399 : : hc->xfer_buff, grxsts.b.bcnt);
400 : :
401 : : /* Update the HC fields for the next packet received. */
402 : 0 : hc->xfer_count += grxsts.b.bcnt;
403 : 0 : hc->xfer_buff += grxsts.b.bcnt;
404 : : }
405 : :
406 : : case DWC_GRXSTS_PKTSTS_IN_XFER_COMP:
407 : : case DWC_GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
408 : : case DWC_GRXSTS_PKTSTS_CH_HALTED:
409 : : /* Handled in interrupt, just ignore data */
410 : : break;
411 : : default:
412 : 0 : DWC_ERROR("RX_STS_Q Interrupt: Unknown status %d\n",
413 : : grxsts.b.pktsts);
414 : 0 : break;
415 : : }
416 : :
417 : : return 1;
418 : : }
419 : :
420 : : /** This interrupt occurs when the non-periodic Tx FIFO is half-empty. More
421 : : * data packets may be written to the FIFO for OUT transfers. More requests
422 : : * may be written to the non-periodic request queue for IN transfers. This
423 : : * interrupt is enabled only in Slave mode. */
424 : 0 : int32_t dwc_otg_hcd_handle_np_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
425 : : {
426 : : DWC_DEBUGPL(DBG_HCD, "--Non-Periodic TxFIFO Empty Interrupt--\n");
427 : 0 : dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
428 : : DWC_OTG_TRANSACTION_NON_PERIODIC);
429 : 0 : return 1;
430 : : }
431 : :
432 : : /** This interrupt occurs when the periodic Tx FIFO is half-empty. More data
433 : : * packets may be written to the FIFO for OUT transfers. More requests may be
434 : : * written to the periodic request queue for IN transfers. This interrupt is
435 : : * enabled only in Slave mode. */
436 : 0 : int32_t dwc_otg_hcd_handle_perio_tx_fifo_empty_intr(dwc_otg_hcd_t * dwc_otg_hcd)
437 : : {
438 : : DWC_DEBUGPL(DBG_HCD, "--Periodic TxFIFO Empty Interrupt--\n");
439 : 0 : dwc_otg_hcd_queue_transactions(dwc_otg_hcd,
440 : : DWC_OTG_TRANSACTION_PERIODIC);
441 : 0 : return 1;
442 : : }
443 : :
444 : : /** There are multiple conditions that can cause a port interrupt. This function
445 : : * determines which interrupt conditions have occurred and handles them
446 : : * appropriately. */
447 : 828 : int32_t dwc_otg_hcd_handle_port_intr(dwc_otg_hcd_t * dwc_otg_hcd)
448 : : {
449 : : int retval = 0;
450 : : hprt0_data_t hprt0;
451 : : hprt0_data_t hprt0_modify;
452 : :
453 : 828 : hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
454 : 828 : hprt0_modify.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
455 : :
456 : : /* Clear appropriate bits in HPRT0 to clear the interrupt bit in
457 : : * GINTSTS */
458 : :
459 : 828 : hprt0_modify.b.prtena = 0;
460 : 828 : hprt0_modify.b.prtconndet = 0;
461 : 828 : hprt0_modify.b.prtenchng = 0;
462 : 828 : hprt0_modify.b.prtovrcurrchng = 0;
463 : :
464 : : /* Port Connect Detected
465 : : * Set flag and clear if detected */
466 [ - + ]: 828 : if (dwc_otg_hcd->core_if->hibernation_suspend == 1) {
467 : : // Dont modify port status if we are in hibernation state
468 : 0 : hprt0_modify.b.prtconndet = 1;
469 : 0 : hprt0_modify.b.prtenchng = 1;
470 : 0 : DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
471 : 0 : hprt0.d32 = DWC_READ_REG32(dwc_otg_hcd->core_if->host_if->hprt0);
472 : 0 : return retval;
473 : : }
474 : :
475 [ + + ]: 828 : if (hprt0.b.prtconndet) {
476 : : /** @todo - check if steps performed in 'else' block should be perfromed regardles adp */
477 [ - + # # ]: 207 : if (dwc_otg_hcd->core_if->adp_enable &&
478 : 0 : dwc_otg_hcd->core_if->adp.vbuson_timer_started == 1) {
479 : 0 : DWC_PRINTF("PORT CONNECT DETECTED ----------------\n");
480 : 0 : DWC_TIMER_CANCEL(dwc_otg_hcd->core_if->adp.vbuson_timer);
481 : 0 : dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;
482 : : /* TODO - check if this is required, as
483 : : * host initialization was already performed
484 : : * after initial ADP probing
485 : : */
486 : : /*dwc_otg_hcd->core_if->adp.vbuson_timer_started = 0;
487 : : dwc_otg_core_init(dwc_otg_hcd->core_if);
488 : : dwc_otg_enable_global_interrupts(dwc_otg_hcd->core_if);
489 : : cil_hcd_start(dwc_otg_hcd->core_if);*/
490 : : } else {
491 : :
492 : : DWC_DEBUGPL(DBG_HCD, "--Port Interrupt HPRT0=0x%08x "
493 : : "Port Connect Detected--\n", hprt0.d32);
494 : 207 : dwc_otg_hcd->flags.b.port_connect_status_change = 1;
495 : 207 : dwc_otg_hcd->flags.b.port_connect_status = 1;
496 : 207 : hprt0_modify.b.prtconndet = 1;
497 : :
498 : : /* B-Device has connected, Delete the connection timer. */
499 : 207 : DWC_TIMER_CANCEL(dwc_otg_hcd->conn_timer);
500 : : }
501 : : /* The Hub driver asserts a reset when it sees port connect
502 : : * status change flag */
503 : : retval |= 1;
504 : : }
505 : :
506 : : /* Port Enable Changed
507 : : * Clear if detected - Set internal flag if disabled */
508 [ + + ]: 828 : if (hprt0.b.prtenchng) {
509 : : DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x "
510 : : "Port Enable Changed--\n", hprt0.d32);
511 : 621 : hprt0_modify.b.prtenchng = 1;
512 [ + + ]: 621 : if (hprt0.b.prtena == 1) {
513 : : hfir_data_t hfir;
514 : : int do_reset = 0;
515 : 414 : dwc_otg_core_params_t *params =
516 : 414 : dwc_otg_hcd->core_if->core_params;
517 : 414 : dwc_otg_core_global_regs_t *global_regs =
518 : : dwc_otg_hcd->core_if->core_global_regs;
519 : 414 : dwc_otg_host_if_t *host_if =
520 : : dwc_otg_hcd->core_if->host_if;
521 : :
522 : 414 : dwc_otg_hcd->flags.b.port_speed = hprt0.b.prtspd;
523 [ + - ]: 414 : if (microframe_schedule)
524 : 414 : init_hcd_usecs(dwc_otg_hcd);
525 : :
526 : : /* Every time when port enables calculate
527 : : * HFIR.FrInterval
528 : : */
529 : 414 : hfir.d32 = DWC_READ_REG32(&host_if->host_global_regs->hfir);
530 : 414 : hfir.b.frint = calc_frame_interval(dwc_otg_hcd->core_if);
531 : 414 : DWC_WRITE_REG32(&host_if->host_global_regs->hfir, hfir.d32);
532 : :
533 : : /* Check if we need to adjust the PHY clock speed for
534 : : * low power and adjust it */
535 [ - + ]: 414 : if (params->host_support_fs_ls_low_power) {
536 : : gusbcfg_data_t usbcfg;
537 : :
538 : 0 : usbcfg.d32 =
539 : 0 : DWC_READ_REG32(&global_regs->gusbcfg);
540 : :
541 [ # # ]: 0 : if (hprt0.b.prtspd == DWC_HPRT0_PRTSPD_LOW_SPEED
542 : 0 : || hprt0.b.prtspd ==
543 : : DWC_HPRT0_PRTSPD_FULL_SPEED) {
544 : : /*
545 : : * Low power
546 : : */
547 : : hcfg_data_t hcfg;
548 [ # # ]: 0 : if (usbcfg.b.phylpwrclksel == 0) {
549 : : /* Set PHY low power clock select for FS/LS devices */
550 : 0 : usbcfg.b.phylpwrclksel = 1;
551 : 0 : DWC_WRITE_REG32
552 : : (&global_regs->gusbcfg,
553 : : usbcfg.d32);
554 : : do_reset = 1;
555 : : }
556 : :
557 : 0 : hcfg.d32 =
558 : 0 : DWC_READ_REG32
559 : 0 : (&host_if->host_global_regs->hcfg);
560 : :
561 [ # # ]: 0 : if (hprt0.b.prtspd ==
562 : : DWC_HPRT0_PRTSPD_LOW_SPEED
563 [ # # ]: 0 : && params->host_ls_low_power_phy_clk
564 : : ==
565 : : DWC_HOST_LS_LOW_POWER_PHY_CLK_PARAM_6MHZ)
566 : : {
567 : : /* 6 MHZ */
568 : : DWC_DEBUGPL(DBG_CIL,
569 : : "FS_PHY programming HCFG to 6 MHz (Low Power)\n");
570 [ # # ]: 0 : if (hcfg.b.fslspclksel !=
571 : : DWC_HCFG_6_MHZ) {
572 : 0 : hcfg.b.fslspclksel =
573 : : DWC_HCFG_6_MHZ;
574 : 0 : DWC_WRITE_REG32
575 : 0 : (&host_if->host_global_regs->hcfg,
576 : : hcfg.d32);
577 : : do_reset = 1;
578 : : }
579 : : } else {
580 : : /* 48 MHZ */
581 : : DWC_DEBUGPL(DBG_CIL,
582 : : "FS_PHY programming HCFG to 48 MHz ()\n");
583 [ # # ]: 0 : if (hcfg.b.fslspclksel !=
584 : : DWC_HCFG_48_MHZ) {
585 : 0 : hcfg.b.fslspclksel =
586 : : DWC_HCFG_48_MHZ;
587 : 0 : DWC_WRITE_REG32
588 : 0 : (&host_if->host_global_regs->hcfg,
589 : : hcfg.d32);
590 : : do_reset = 1;
591 : : }
592 : : }
593 : : } else {
594 : : /*
595 : : * Not low power
596 : : */
597 [ # # ]: 0 : if (usbcfg.b.phylpwrclksel == 1) {
598 : 0 : usbcfg.b.phylpwrclksel = 0;
599 : 0 : DWC_WRITE_REG32
600 : : (&global_regs->gusbcfg,
601 : : usbcfg.d32);
602 : : do_reset = 1;
603 : : }
604 : : }
605 : :
606 [ # # ]: 0 : if (do_reset) {
607 : 0 : DWC_TASK_SCHEDULE(dwc_otg_hcd->reset_tasklet);
608 : : }
609 : : }
610 : :
611 [ + - ]: 414 : if (!do_reset) {
612 : : /* Port has been enabled set the reset change flag */
613 : 414 : dwc_otg_hcd->flags.b.port_reset_change = 1;
614 : : }
615 : : } else {
616 : 207 : dwc_otg_hcd->flags.b.port_enable_change = 1;
617 : : }
618 : : retval |= 1;
619 : : }
620 : :
621 : : /** Overcurrent Change Interrupt */
622 [ - + ]: 828 : if (hprt0.b.prtovrcurrchng) {
623 : : DWC_DEBUGPL(DBG_HCD, " --Port Interrupt HPRT0=0x%08x "
624 : : "Port Overcurrent Changed--\n", hprt0.d32);
625 : 0 : dwc_otg_hcd->flags.b.port_over_current_change = 1;
626 : 0 : hprt0_modify.b.prtovrcurrchng = 1;
627 : : retval |= 1;
628 : : }
629 : :
630 : : /* Clear Port Interrupts */
631 : 828 : DWC_WRITE_REG32(dwc_otg_hcd->core_if->host_if->hprt0, hprt0_modify.d32);
632 : :
633 : 828 : return retval;
634 : : }
635 : :
636 : : /** This interrupt indicates that one or more host channels has a pending
637 : : * interrupt. There are multiple conditions that can cause each host channel
638 : : * interrupt. This function determines which conditions have occurred for each
639 : : * host channel interrupt and handles them appropriately. */
640 : 6811830 : int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd)
641 : : {
642 : : int i;
643 : : int retval = 0;
644 : 6811830 : haint_data_t haint = { .d32 = 0 } ;
645 : :
646 : : /* Clear appropriate bits in HCINTn to clear the interrupt bit in
647 : : * GINTSTS */
648 : :
649 [ - + ]: 6811830 : if (!fiq_fsm_enable)
650 : 0 : haint.d32 = dwc_otg_read_host_all_channels_intr(dwc_otg_hcd->core_if);
651 : :
652 : : // Overwrite with saved interrupts from fiq handler
653 [ + - ]: 6811830 : if(fiq_fsm_enable)
654 : : {
655 : : /* check the mask? */
656 : 6811830 : local_fiq_disable();
657 : 6811830 : fiq_fsm_spin_lock(&dwc_otg_hcd->fiq_state->lock);
658 : 6811830 : haint.b2.chint |= ~(dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint);
659 : 6811830 : dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint = ~0;
660 : 6811830 : fiq_fsm_spin_unlock(&dwc_otg_hcd->fiq_state->lock);
661 : 6811830 : local_fiq_enable();
662 : : }
663 : :
664 [ + + ]: 54494633 : for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) {
665 [ + + ]: 54494634 : if (haint.b2.chint & (1 << i)) {
666 : 7080606 : retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i);
667 : : }
668 : : }
669 : :
670 : 6811829 : return retval;
671 : : }
672 : :
673 : : /**
674 : : * Gets the actual length of a transfer after the transfer halts. _halt_status
675 : : * holds the reason for the halt.
676 : : *
677 : : * For IN transfers where halt_status is DWC_OTG_HC_XFER_COMPLETE,
678 : : * *short_read is set to 1 upon return if less than the requested
679 : : * number of bytes were transferred. Otherwise, *short_read is set to 0 upon
680 : : * return. short_read may also be NULL on entry, in which case it remains
681 : : * unchanged.
682 : : */
683 : 123759 : static uint32_t get_actual_xfer_length(dwc_hc_t * hc,
684 : : dwc_otg_hc_regs_t * hc_regs,
685 : : dwc_otg_qtd_t * qtd,
686 : : dwc_otg_halt_status_e halt_status,
687 : : int *short_read)
688 : : {
689 : : hctsiz_data_t hctsiz;
690 : : uint32_t length;
691 : :
692 [ + - ]: 123759 : if (short_read != NULL) {
693 : 123759 : *short_read = 0;
694 : : }
695 : 123759 : hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
696 : :
697 [ + - ]: 123759 : if (halt_status == DWC_OTG_HC_XFER_COMPLETE) {
698 [ + + ]: 123759 : if (hc->ep_is_in) {
699 : 80776 : length = hc->xfer_len - hctsiz.b.xfersize;
700 [ + - ]: 80776 : if (short_read != NULL) {
701 : 80776 : *short_read = (hctsiz.b.xfersize != 0);
702 : : }
703 [ + + ]: 42983 : } else if (hc->qh->do_split) {
704 : : //length = split_out_xfersize[hc->hc_num];
705 : 207 : length = qtd->ssplit_out_xfer_count;
706 : : } else {
707 : 42776 : length = hc->xfer_len;
708 : : }
709 : : } else {
710 : : /*
711 : : * Must use the hctsiz.pktcnt field to determine how much data
712 : : * has been transferred. This field reflects the number of
713 : : * packets that have been transferred via the USB. This is
714 : : * always an integral number of packets if the transfer was
715 : : * halted before its normal completion. (Can't use the
716 : : * hctsiz.xfersize field because that reflects the number of
717 : : * bytes transferred via the AHB, not the USB).
718 : : */
719 : 0 : length =
720 : 0 : (hc->start_pkt_count - hctsiz.b.pktcnt) * hc->max_packet;
721 : : }
722 : :
723 : 123759 : return length;
724 : : }
725 : :
726 : : /**
727 : : * Updates the state of the URB after a Transfer Complete interrupt on the
728 : : * host channel. Updates the actual_length field of the URB based on the
729 : : * number of bytes transferred via the host channel. Sets the URB status
730 : : * if the data transfer is finished.
731 : : *
732 : : * @return 1 if the data transfer specified by the URB is completely finished,
733 : : * 0 otherwise.
734 : : */
735 : 123759 : static int update_urb_state_xfer_comp(dwc_hc_t * hc,
736 : : dwc_otg_hc_regs_t * hc_regs,
737 : : dwc_otg_hcd_urb_t * urb,
738 : : dwc_otg_qtd_t * qtd)
739 : : {
740 : : int xfer_done = 0;
741 : 123759 : int short_read = 0;
742 : :
743 : : int xfer_length;
744 : :
745 : 123759 : xfer_length = get_actual_xfer_length(hc, hc_regs, qtd,
746 : : DWC_OTG_HC_XFER_COMPLETE,
747 : : &short_read);
748 : :
749 [ - + ]: 123759 : if (urb->actual_length + xfer_length > urb->length) {
750 [ # # ]: 0 : printk_once(KERN_DEBUG "dwc_otg: DEVICE:%03d : %s:%d:trimming xfer length\n",
751 : : hc->dev_addr, __func__, __LINE__);
752 : 0 : xfer_length = urb->length - urb->actual_length;
753 : : }
754 : :
755 : : /* non DWORD-aligned buffer case handling. */
756 [ + + + - : 123759 : if (hc->align_buff && xfer_length && hc->ep_is_in) {
+ + ]
757 : 207 : dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
758 : : xfer_length);
759 : : }
760 : :
761 : 123759 : urb->actual_length += xfer_length;
762 : :
763 [ + - + + : 141425 : if (xfer_length && (hc->ep_type == DWC_OTG_EP_TYPE_BULK) &&
- + ]
764 : 17666 : (urb->flags & URB_SEND_ZERO_PACKET)
765 [ # # ]: 0 : && (urb->actual_length == urb->length)
766 [ # # ]: 0 : && !(urb->length % hc->max_packet)) {
767 : : xfer_done = 0;
768 [ + + + + ]: 123759 : } else if (short_read || urb->actual_length >= urb->length) {
769 : : xfer_done = 1;
770 : 112167 : urb->status = 0;
771 : : }
772 : :
773 : : #ifdef DEBUG
774 : : {
775 : : hctsiz_data_t hctsiz;
776 : : hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
777 : : DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
778 : : __func__, (hc->ep_is_in ? "IN" : "OUT"),
779 : : hc->hc_num);
780 : : DWC_DEBUGPL(DBG_HCDV, " hc->xfer_len %d\n", hc->xfer_len);
781 : : DWC_DEBUGPL(DBG_HCDV, " hctsiz.xfersize %d\n",
782 : : hctsiz.b.xfersize);
783 : : DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n",
784 : : urb->length);
785 : : DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n",
786 : : urb->actual_length);
787 : : DWC_DEBUGPL(DBG_HCDV, " short_read %d, xfer_done %d\n",
788 : : short_read, xfer_done);
789 : : }
790 : : #endif
791 : :
792 : 123759 : return xfer_done;
793 : : }
794 : :
795 : : /*
796 : : * Save the starting data toggle for the next transfer. The data toggle is
797 : : * saved in the QH for non-control transfers and it's saved in the QTD for
798 : : * control transfers.
799 : : */
800 : 29479 : void dwc_otg_hcd_save_data_toggle(dwc_hc_t * hc,
801 : : dwc_otg_hc_regs_t * hc_regs, dwc_otg_qtd_t * qtd)
802 : : {
803 : : hctsiz_data_t hctsiz;
804 : 29479 : hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
805 : :
806 [ + + ]: 29479 : if (hc->ep_type != DWC_OTG_EP_TYPE_CONTROL) {
807 : 17887 : dwc_otg_qh_t *qh = hc->qh;
808 [ + + ]: 17887 : if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
809 : 8727 : qh->data_toggle = DWC_OTG_HC_PID_DATA0;
810 : : } else {
811 : 9160 : qh->data_toggle = DWC_OTG_HC_PID_DATA1;
812 : : }
813 : : } else {
814 [ + + ]: 11592 : if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
815 : 6624 : qtd->data_toggle = DWC_OTG_HC_PID_DATA0;
816 : : } else {
817 : 4968 : qtd->data_toggle = DWC_OTG_HC_PID_DATA1;
818 : : }
819 : : }
820 : 29479 : }
821 : :
822 : : /**
823 : : * Updates the state of an Isochronous URB when the transfer is stopped for
824 : : * any reason. The fields of the current entry in the frame descriptor array
825 : : * are set based on the transfer state and the input _halt_status. Completes
826 : : * the Isochronous URB if all the URB frames have been completed.
827 : : *
828 : : * @return DWC_OTG_HC_XFER_COMPLETE if there are more frames remaining to be
829 : : * transferred in the URB. Otherwise return DWC_OTG_HC_XFER_URB_COMPLETE.
830 : : */
831 : : static dwc_otg_halt_status_e
832 : 0 : update_isoc_urb_state(dwc_otg_hcd_t * hcd,
833 : : dwc_hc_t * hc,
834 : : dwc_otg_hc_regs_t * hc_regs,
835 : : dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
836 : : {
837 : 0 : dwc_otg_hcd_urb_t *urb = qtd->urb;
838 : : dwc_otg_halt_status_e ret_val = halt_status;
839 : : struct dwc_otg_hcd_iso_packet_desc *frame_desc;
840 : :
841 : 0 : frame_desc = &urb->iso_descs[qtd->isoc_frame_index];
842 [ # # # # : 0 : switch (halt_status) {
# ]
843 : : case DWC_OTG_HC_XFER_COMPLETE:
844 : 0 : frame_desc->status = 0;
845 : 0 : frame_desc->actual_length =
846 : 0 : get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
847 : :
848 : : /* non DWORD-aligned buffer case handling. */
849 [ # # # # : 0 : if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
# # ]
850 : 0 : dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
851 : 0 : hc->qh->dw_align_buf, frame_desc->actual_length);
852 : : }
853 : :
854 : : break;
855 : : case DWC_OTG_HC_XFER_FRAME_OVERRUN:
856 : 0 : urb->error_count++;
857 [ # # ]: 0 : if (hc->ep_is_in) {
858 : 0 : frame_desc->status = -DWC_E_NO_STREAM_RES;
859 : : } else {
860 : 0 : frame_desc->status = -DWC_E_COMMUNICATION;
861 : : }
862 : 0 : frame_desc->actual_length = 0;
863 : 0 : break;
864 : : case DWC_OTG_HC_XFER_BABBLE_ERR:
865 : 0 : urb->error_count++;
866 : 0 : frame_desc->status = -DWC_E_OVERFLOW;
867 : : /* Don't need to update actual_length in this case. */
868 : 0 : break;
869 : : case DWC_OTG_HC_XFER_XACT_ERR:
870 : 0 : urb->error_count++;
871 : 0 : frame_desc->status = -DWC_E_PROTOCOL;
872 : 0 : frame_desc->actual_length =
873 : 0 : get_actual_xfer_length(hc, hc_regs, qtd, halt_status, NULL);
874 : :
875 : : /* non DWORD-aligned buffer case handling. */
876 [ # # # # : 0 : if (hc->align_buff && frame_desc->actual_length && hc->ep_is_in) {
# # ]
877 : 0 : dwc_memcpy(urb->buf + frame_desc->offset + qtd->isoc_split_offset,
878 : 0 : hc->qh->dw_align_buf, frame_desc->actual_length);
879 : : }
880 : : /* Skip whole frame */
881 [ # # # # ]: 0 : if (hc->qh->do_split && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC) &&
882 [ # # ]: 0 : hc->ep_is_in && hcd->core_if->dma_enable) {
883 : 0 : qtd->complete_split = 0;
884 : 0 : qtd->isoc_split_offset = 0;
885 : : }
886 : :
887 : : break;
888 : : default:
889 : : DWC_ASSERT(1, "Unhandled _halt_status (%d)\n", halt_status);
890 : : break;
891 : : }
892 [ # # ]: 0 : if (++qtd->isoc_frame_index == urb->packet_count) {
893 : : /*
894 : : * urb->status is not used for isoc transfers.
895 : : * The individual frame_desc statuses are used instead.
896 : : */
897 : 0 : hcd->fops->complete(hcd, urb->priv, urb, 0);
898 : : ret_val = DWC_OTG_HC_XFER_URB_COMPLETE;
899 : : } else {
900 : : ret_val = DWC_OTG_HC_XFER_COMPLETE;
901 : : }
902 : 0 : return ret_val;
903 : : }
904 : :
905 : : /**
906 : : * Frees the first QTD in the QH's list if free_qtd is 1. For non-periodic
907 : : * QHs, removes the QH from the active non-periodic schedule. If any QTDs are
908 : : * still linked to the QH, the QH is added to the end of the inactive
909 : : * non-periodic schedule. For periodic QHs, removes the QH from the periodic
910 : : * schedule if no more QTDs are linked to the QH.
911 : : */
912 : 7074083 : static void deactivate_qh(dwc_otg_hcd_t * hcd, dwc_otg_qh_t * qh, int free_qtd)
913 : : {
914 : : int continue_split = 0;
915 : : dwc_otg_qtd_t *qtd;
916 : :
917 : : DWC_DEBUGPL(DBG_HCDV, " %s(%p,%p,%d)\n", __func__, hcd, qh, free_qtd);
918 : :
919 : 7074083 : qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
920 : :
921 [ + - ]: 7074083 : if (qtd->complete_split) {
922 : : continue_split = 1;
923 [ - + ]: 7074083 : } else if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_MID ||
924 : : qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_END) {
925 : : continue_split = 1;
926 : : }
927 : :
928 [ + + ]: 7074083 : if (free_qtd) {
929 : 119205 : dwc_otg_hcd_qtd_remove_and_free(hcd, qtd, qh);
930 : : continue_split = 0;
931 : : }
932 : :
933 : 7074083 : qh->channel = NULL;
934 : 7074083 : dwc_otg_hcd_qh_deactivate(hcd, qh, continue_split);
935 : 7074083 : }
936 : :
937 : : /**
938 : : * Releases a host channel for use by other transfers. Attempts to select and
939 : : * queue more transactions since at least one host channel is available.
940 : : *
941 : : * @param hcd The HCD state structure.
942 : : * @param hc The host channel to release.
943 : : * @param qtd The QTD associated with the host channel. This QTD may be freed
944 : : * if the transfer is complete or an error has occurred.
945 : : * @param halt_status Reason the channel is being released. This status
946 : : * determines the actions taken by this function.
947 : : */
948 : 7080597 : static void release_channel(dwc_otg_hcd_t * hcd,
949 : : dwc_hc_t * hc,
950 : : dwc_otg_qtd_t * qtd,
951 : : dwc_otg_halt_status_e halt_status)
952 : : {
953 : : dwc_otg_transaction_type_e tr_type;
954 : : int free_qtd;
955 : :
956 : : int hog_port = 0;
957 : :
958 : : DWC_DEBUGPL(DBG_HCDV, " %s: channel %d, halt_status %d, xfer_len %d\n",
959 : : __func__, hc->hc_num, halt_status, hc->xfer_len);
960 : :
961 : : if(fiq_fsm_enable && hc->do_split) {
962 : : if(!hc->ep_is_in && hc->ep_type == UE_ISOCHRONOUS) {
963 : : if(hc->xact_pos == DWC_HCSPLIT_XACTPOS_MID ||
964 : : hc->xact_pos == DWC_HCSPLIT_XACTPOS_BEGIN) {
965 : : hog_port = 0;
966 : : }
967 : : }
968 : : }
969 : :
970 [ - - - + : 7080597 : switch (halt_status) {
+ + ]
971 : : case DWC_OTG_HC_XFER_URB_COMPLETE:
972 : : free_qtd = 1;
973 : : break;
974 : : case DWC_OTG_HC_XFER_AHB_ERR:
975 : : case DWC_OTG_HC_XFER_STALL:
976 : : case DWC_OTG_HC_XFER_BABBLE_ERR:
977 : : free_qtd = 1;
978 : : break;
979 : : case DWC_OTG_HC_XFER_XACT_ERR:
980 [ # # ]: 0 : if (qtd->error_count >= 3) {
981 : : DWC_DEBUGPL(DBG_HCDV,
982 : : " Complete URB with transaction error\n");
983 : : free_qtd = 1;
984 : 0 : qtd->urb->status = -DWC_E_PROTOCOL;
985 : 0 : hcd->fops->complete(hcd, qtd->urb->priv,
986 : : qtd->urb, -DWC_E_PROTOCOL);
987 : : } else {
988 : : free_qtd = 0;
989 : : }
990 : : break;
991 : : case DWC_OTG_HC_XFER_URB_DEQUEUE:
992 : : /*
993 : : * The QTD has already been removed and the QH has been
994 : : * deactivated. Don't want to do anything except release the
995 : : * host channel and try to queue more transfers.
996 : : */
997 : : goto cleanup;
998 : : case DWC_OTG_HC_XFER_NO_HALT_STATUS:
999 : : free_qtd = 0;
1000 : 0 : break;
1001 : : case DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE:
1002 : : DWC_DEBUGPL(DBG_HCDV,
1003 : : " Complete URB with I/O error\n");
1004 : : free_qtd = 1;
1005 : 0 : qtd->urb->status = -DWC_E_IO;
1006 : 0 : hcd->fops->complete(hcd, qtd->urb->priv,
1007 : : qtd->urb, -DWC_E_IO);
1008 : 0 : break;
1009 : : default:
1010 : : free_qtd = 0;
1011 : 6954876 : break;
1012 : : }
1013 : :
1014 : 7074081 : deactivate_qh(hcd, hc->qh, free_qtd);
1015 : :
1016 : : cleanup:
1017 : : /*
1018 : : * Release the host channel for use by other transfers. The cleanup
1019 : : * function clears the channel interrupt enables and conditions, so
1020 : : * there's no need to clear the Channel Halted interrupt separately.
1021 : : */
1022 [ + - + + ]: 7080597 : if (fiq_fsm_enable && hcd->fiq_state->channel[hc->hc_num].fsm != FIQ_PASSTHROUGH)
1023 : 4332205 : dwc_otg_cleanup_fiq_channel(hcd, hc->hc_num);
1024 : 7080596 : dwc_otg_hc_cleanup(hcd->core_if, hc);
1025 [ - + ]: 7080596 : DWC_CIRCLEQ_INSERT_TAIL(&hcd->free_hc_list, hc, hc_list_entry);
1026 : :
1027 [ - + ]: 7080596 : if (!microframe_schedule) {
1028 [ # # ]: 0 : switch (hc->ep_type) {
1029 : : case DWC_OTG_EP_TYPE_CONTROL:
1030 : : case DWC_OTG_EP_TYPE_BULK:
1031 : 0 : hcd->non_periodic_channels--;
1032 : 0 : break;
1033 : :
1034 : : default:
1035 : : /*
1036 : : * Don't release reservations for periodic channels here.
1037 : : * That's done when a periodic transfer is descheduled (i.e.
1038 : : * when the QH is removed from the periodic schedule).
1039 : : */
1040 : : break;
1041 : : }
1042 : : } else {
1043 : 7080596 : hcd->available_host_channels++;
1044 : : fiq_print(FIQDBG_INT, hcd->fiq_state, "AHC = %d ", hcd->available_host_channels);
1045 : : }
1046 : :
1047 : : /* Try to queue more transfers now that there's a free channel. */
1048 : 7080596 : tr_type = dwc_otg_hcd_select_transactions(hcd);
1049 [ + + ]: 7080596 : if (tr_type != DWC_OTG_TRANSACTION_NONE) {
1050 : 6285866 : dwc_otg_hcd_queue_transactions(hcd, tr_type);
1051 : : }
1052 : 7080596 : }
1053 : :
1054 : : /**
1055 : : * Halts a host channel. If the channel cannot be halted immediately because
1056 : : * the request queue is full, this function ensures that the FIFO empty
1057 : : * interrupt for the appropriate queue is enabled so that the halt request can
1058 : : * be queued when there is space in the request queue.
1059 : : *
1060 : : * This function may also be called in DMA mode. In that case, the channel is
1061 : : * simply released since the core always halts the channel automatically in
1062 : : * DMA mode.
1063 : : */
1064 : 6868366 : static void halt_channel(dwc_otg_hcd_t * hcd,
1065 : : dwc_hc_t * hc,
1066 : : dwc_otg_qtd_t * qtd, dwc_otg_halt_status_e halt_status)
1067 : : {
1068 [ + - ]: 6868366 : if (hcd->core_if->dma_enable) {
1069 : 6868366 : release_channel(hcd, hc, qtd, halt_status);
1070 : 13736732 : return;
1071 : : }
1072 : :
1073 : : /* Slave mode processing... */
1074 : 0 : dwc_otg_hc_halt(hcd->core_if, hc, halt_status);
1075 : :
1076 [ # # ]: 0 : if (hc->halt_on_queue) {
1077 : 0 : gintmsk_data_t gintmsk = {.d32 = 0 };
1078 : : dwc_otg_core_global_regs_t *global_regs;
1079 : 0 : global_regs = hcd->core_if->core_global_regs;
1080 : :
1081 [ # # ]: 0 : if (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
1082 : : hc->ep_type == DWC_OTG_EP_TYPE_BULK) {
1083 : : /*
1084 : : * Make sure the Non-periodic Tx FIFO empty interrupt
1085 : : * is enabled so that the non-periodic schedule will
1086 : : * be processed.
1087 : : */
1088 : 0 : gintmsk.b.nptxfempty = 1;
1089 [ # # ]: 0 : if (fiq_enable) {
1090 : 0 : local_fiq_disable();
1091 : 0 : fiq_fsm_spin_lock(&hcd->fiq_state->lock);
1092 : 0 : DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
1093 : 0 : fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
1094 : 0 : local_fiq_enable();
1095 : : } else {
1096 : 0 : DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
1097 : : }
1098 : : } else {
1099 : : /*
1100 : : * Move the QH from the periodic queued schedule to
1101 : : * the periodic assigned schedule. This allows the
1102 : : * halt to be queued when the periodic schedule is
1103 : : * processed.
1104 : : */
1105 : 0 : DWC_LIST_MOVE_HEAD(&hcd->periodic_sched_assigned,
1106 : : &hc->qh->qh_list_entry);
1107 : :
1108 : : /*
1109 : : * Make sure the Periodic Tx FIFO Empty interrupt is
1110 : : * enabled so that the periodic schedule will be
1111 : : * processed.
1112 : : */
1113 : 0 : gintmsk.b.ptxfempty = 1;
1114 [ # # ]: 0 : if (fiq_enable) {
1115 : 0 : local_fiq_disable();
1116 : 0 : fiq_fsm_spin_lock(&hcd->fiq_state->lock);
1117 : 0 : DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
1118 : 0 : fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
1119 : 0 : local_fiq_enable();
1120 : : } else {
1121 : 0 : DWC_MODIFY_REG32(&global_regs->gintmsk, 0, gintmsk.d32);
1122 : : }
1123 : : }
1124 : : }
1125 : : }
1126 : :
1127 : : /**
1128 : : * Performs common cleanup for non-periodic transfers after a Transfer
1129 : : * Complete interrupt. This function should be called after any endpoint type
1130 : : * specific handling is finished to release the host channel.
1131 : : */
1132 : 325967 : static void complete_non_periodic_xfer(dwc_otg_hcd_t * hcd,
1133 : : dwc_hc_t * hc,
1134 : : dwc_otg_hc_regs_t * hc_regs,
1135 : : dwc_otg_qtd_t * qtd,
1136 : : dwc_otg_halt_status_e halt_status)
1137 : : {
1138 : : hcint_data_t hcint;
1139 : :
1140 : 325967 : qtd->error_count = 0;
1141 : :
1142 : 325967 : hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
1143 [ - + ]: 325967 : if (hcint.b.nyet) {
1144 : : /*
1145 : : * Got a NYET on the last transaction of the transfer. This
1146 : : * means that the endpoint should be in the PING state at the
1147 : : * beginning of the next transfer.
1148 : : */
1149 : 0 : hc->qh->ping_state = 1;
1150 : 0 : clear_hc_int(hc_regs, nyet);
1151 : : }
1152 : :
1153 : : /*
1154 : : * Always halt and release the host channel to make it available for
1155 : : * more transfers. There may still be more phases for a control
1156 : : * transfer or more data packets for a bulk transfer at this point,
1157 : : * but the host channel is still halted. A channel will be reassigned
1158 : : * to the transfer when the non-periodic schedule is processed after
1159 : : * the channel is released. This allows transactions to be queued
1160 : : * properly via dwc_otg_hcd_queue_transactions, which also enables the
1161 : : * Tx FIFO Empty interrupt if necessary.
1162 : : */
1163 [ + + ]: 325967 : if (hc->ep_is_in) {
1164 : : /*
1165 : : * IN transfers in Slave mode require an explicit disable to
1166 : : * halt the channel. (In DMA mode, this call simply releases
1167 : : * the channel.)
1168 : : */
1169 : 120475 : halt_channel(hcd, hc, qtd, halt_status);
1170 : : } else {
1171 : : /*
1172 : : * The channel is automatically disabled by the core for OUT
1173 : : * transfers in Slave mode.
1174 : : */
1175 : 205492 : release_channel(hcd, hc, qtd, halt_status);
1176 : : }
1177 : 325967 : }
1178 : :
1179 : : /**
1180 : : * Performs common cleanup for periodic transfers after a Transfer Complete
1181 : : * interrupt. This function should be called after any endpoint type specific
1182 : : * handling is finished to release the host channel.
1183 : : */
1184 : 221 : static void complete_periodic_xfer(dwc_otg_hcd_t * hcd,
1185 : : dwc_hc_t * hc,
1186 : : dwc_otg_hc_regs_t * hc_regs,
1187 : : dwc_otg_qtd_t * qtd,
1188 : : dwc_otg_halt_status_e halt_status)
1189 : : {
1190 : : hctsiz_data_t hctsiz;
1191 : 221 : qtd->error_count = 0;
1192 : :
1193 : 221 : hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
1194 [ + - + - ]: 221 : if (!hc->ep_is_in || hctsiz.b.pktcnt == 0) {
1195 : : /* Core halts channel in these cases. */
1196 : 221 : release_channel(hcd, hc, qtd, halt_status);
1197 : : } else {
1198 : : /* Flush any outstanding requests from the Tx queue. */
1199 : 0 : halt_channel(hcd, hc, qtd, halt_status);
1200 : : }
1201 : 221 : }
1202 : :
1203 : 0 : static int32_t handle_xfercomp_isoc_split_in(dwc_otg_hcd_t * hcd,
1204 : : dwc_hc_t * hc,
1205 : : dwc_otg_hc_regs_t * hc_regs,
1206 : : dwc_otg_qtd_t * qtd)
1207 : : {
1208 : : uint32_t len;
1209 : : struct dwc_otg_hcd_iso_packet_desc *frame_desc;
1210 : 0 : frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
1211 : :
1212 : 0 : len = get_actual_xfer_length(hc, hc_regs, qtd,
1213 : : DWC_OTG_HC_XFER_COMPLETE, NULL);
1214 : :
1215 [ # # ]: 0 : if (!len) {
1216 : 0 : qtd->complete_split = 0;
1217 : 0 : qtd->isoc_split_offset = 0;
1218 : 0 : return 0;
1219 : : }
1220 : 0 : frame_desc->actual_length += len;
1221 : :
1222 [ # # # # ]: 0 : if (hc->align_buff && len)
1223 : 0 : dwc_memcpy(qtd->urb->buf + frame_desc->offset +
1224 : 0 : qtd->isoc_split_offset, hc->qh->dw_align_buf, len);
1225 : 0 : qtd->isoc_split_offset += len;
1226 : :
1227 [ # # ]: 0 : if (frame_desc->length == frame_desc->actual_length) {
1228 : 0 : frame_desc->status = 0;
1229 : 0 : qtd->isoc_frame_index++;
1230 : 0 : qtd->complete_split = 0;
1231 : 0 : qtd->isoc_split_offset = 0;
1232 : : }
1233 : :
1234 [ # # ]: 0 : if (qtd->isoc_frame_index == qtd->urb->packet_count) {
1235 : 0 : hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
1236 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
1237 : : } else {
1238 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
1239 : : }
1240 : :
1241 : : return 1; /* Indicates that channel released */
1242 : : }
1243 : :
1244 : : /**
1245 : : * Handles a host channel Transfer Complete interrupt. This handler may be
1246 : : * called in either DMA mode or Slave mode.
1247 : : */
1248 : 326188 : static int32_t handle_hc_xfercomp_intr(dwc_otg_hcd_t * hcd,
1249 : : dwc_hc_t * hc,
1250 : : dwc_otg_hc_regs_t * hc_regs,
1251 : : dwc_otg_qtd_t * qtd)
1252 : : {
1253 : : int urb_xfer_done;
1254 : : dwc_otg_halt_status_e halt_status = DWC_OTG_HC_XFER_COMPLETE;
1255 : 326188 : dwc_otg_hcd_urb_t *urb = qtd->urb;
1256 : 326188 : int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
1257 : :
1258 : : DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
1259 : : "Transfer Complete--\n", hc->hc_num);
1260 : :
1261 [ - + ]: 326188 : if (hcd->core_if->dma_desc_enable) {
1262 : 0 : dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, halt_status);
1263 [ # # ]: 0 : if (pipe_type == UE_ISOCHRONOUS) {
1264 : : /* Do not disable the interrupt, just clear it */
1265 : 0 : clear_hc_int(hc_regs, xfercomp);
1266 : 0 : return 1;
1267 : : }
1268 : : goto handle_xfercomp_done;
1269 : : }
1270 : :
1271 : : /*
1272 : : * Handle xfer complete on CSPLIT.
1273 : : */
1274 : :
1275 [ + + ]: 326188 : if (hc->qh->do_split) {
1276 [ - + ]: 27533 : if ((hc->ep_type == DWC_OTG_EP_TYPE_ISOC) && hc->ep_is_in
1277 [ # # ]: 0 : && hcd->core_if->dma_enable) {
1278 [ # # ]: 0 : if (qtd->complete_split
1279 [ # # ]: 0 : && handle_xfercomp_isoc_split_in(hcd, hc, hc_regs,
1280 : : qtd))
1281 : : goto handle_xfercomp_done;
1282 : : } else {
1283 : 27533 : qtd->complete_split = 0;
1284 : : }
1285 : : }
1286 : :
1287 : : /* Update the QTD and URB states. */
1288 [ + + + - : 326188 : switch (pipe_type) {
- ]
1289 : : case UE_CONTROL:
1290 [ + + + - ]: 308301 : switch (qtd->control_phase) {
1291 : : case DWC_OTG_CONTROL_SETUP:
1292 [ + + ]: 101318 : if (urb->length > 0) {
1293 : 94487 : qtd->control_phase = DWC_OTG_CONTROL_DATA;
1294 : : } else {
1295 : 6831 : qtd->control_phase = DWC_OTG_CONTROL_STATUS;
1296 : : }
1297 : : DWC_DEBUGPL(DBG_HCDV,
1298 : : " Control setup transaction done\n");
1299 : : halt_status = DWC_OTG_HC_XFER_COMPLETE;
1300 : : break;
1301 : : case DWC_OTG_CONTROL_DATA:{
1302 : 105872 : urb_xfer_done =
1303 : : update_urb_state_xfer_comp(hc, hc_regs, urb,
1304 : : qtd);
1305 [ + + ]: 105872 : if (urb_xfer_done) {
1306 : 94280 : qtd->control_phase =
1307 : : DWC_OTG_CONTROL_STATUS;
1308 : : DWC_DEBUGPL(DBG_HCDV,
1309 : : " Control data transfer done\n");
1310 : : } else {
1311 : 11592 : dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
1312 : : }
1313 : : halt_status = DWC_OTG_HC_XFER_COMPLETE;
1314 : : break;
1315 : : }
1316 : : case DWC_OTG_CONTROL_STATUS:
1317 : : DWC_DEBUGPL(DBG_HCDV, " Control transfer complete\n");
1318 [ + + ]: 101111 : if (urb->status == -DWC_E_IN_PROGRESS) {
1319 : 6831 : urb->status = 0;
1320 : : }
1321 : 101111 : hcd->fops->complete(hcd, urb->priv, urb, urb->status);
1322 : : halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
1323 : 101111 : break;
1324 : : }
1325 : :
1326 : 308301 : complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
1327 : 308301 : break;
1328 : : case UE_BULK:
1329 : : DWC_DEBUGPL(DBG_HCDV, " Bulk transfer complete\n");
1330 : 17666 : urb_xfer_done =
1331 : : update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
1332 [ + - ]: 17666 : if (urb_xfer_done) {
1333 : 17666 : hcd->fops->complete(hcd, urb->priv, urb, urb->status);
1334 : : halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
1335 : : } else {
1336 : : halt_status = DWC_OTG_HC_XFER_COMPLETE;
1337 : : }
1338 : :
1339 : 17666 : dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
1340 : 17666 : complete_non_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
1341 : 17666 : break;
1342 : : case UE_INTERRUPT:
1343 : : DWC_DEBUGPL(DBG_HCDV, " Interrupt transfer complete\n");
1344 : 221 : urb_xfer_done =
1345 : : update_urb_state_xfer_comp(hc, hc_regs, urb, qtd);
1346 : :
1347 : : /*
1348 : : * Interrupt URB is done on the first transfer complete
1349 : : * interrupt.
1350 : : */
1351 [ + - ]: 221 : if (urb_xfer_done) {
1352 : 221 : hcd->fops->complete(hcd, urb->priv, urb, urb->status);
1353 : : halt_status = DWC_OTG_HC_XFER_URB_COMPLETE;
1354 : : } else {
1355 : : halt_status = DWC_OTG_HC_XFER_COMPLETE;
1356 : : }
1357 : :
1358 : 221 : dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
1359 : 221 : complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
1360 : 221 : break;
1361 : : case UE_ISOCHRONOUS:
1362 : : DWC_DEBUGPL(DBG_HCDV, " Isochronous transfer complete\n");
1363 [ # # ]: 0 : if (qtd->isoc_split_pos == DWC_HCSPLIT_XACTPOS_ALL) {
1364 : 0 : halt_status =
1365 : : update_isoc_urb_state(hcd, hc, hc_regs, qtd,
1366 : : DWC_OTG_HC_XFER_COMPLETE);
1367 : : }
1368 : 0 : complete_periodic_xfer(hcd, hc, hc_regs, qtd, halt_status);
1369 : 0 : break;
1370 : : }
1371 : :
1372 : : handle_xfercomp_done:
1373 : 326188 : disable_hc_int(hc_regs, xfercompl);
1374 : :
1375 : 326188 : return 1;
1376 : : }
1377 : :
1378 : : /**
1379 : : * Handles a host channel STALL interrupt. This handler may be called in
1380 : : * either DMA mode or Slave mode.
1381 : : */
1382 : 207 : static int32_t handle_hc_stall_intr(dwc_otg_hcd_t * hcd,
1383 : : dwc_hc_t * hc,
1384 : : dwc_otg_hc_regs_t * hc_regs,
1385 : : dwc_otg_qtd_t * qtd)
1386 : : {
1387 : 207 : dwc_otg_hcd_urb_t *urb = qtd->urb;
1388 : 207 : int pipe_type = dwc_otg_hcd_get_pipe_type(&urb->pipe_info);
1389 : :
1390 : : DWC_DEBUGPL(DBG_HCD, "--Host Channel %d Interrupt: "
1391 : : "STALL Received--\n", hc->hc_num);
1392 : :
1393 [ - + ]: 207 : if (hcd->core_if->dma_desc_enable) {
1394 : 0 : dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs, DWC_OTG_HC_XFER_STALL);
1395 : 0 : goto handle_stall_done;
1396 : : }
1397 : :
1398 [ + - ]: 207 : if (pipe_type == UE_CONTROL) {
1399 : 207 : hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
1400 : : }
1401 : :
1402 [ - + ]: 207 : if (pipe_type == UE_BULK || pipe_type == UE_INTERRUPT) {
1403 : 0 : hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_PIPE);
1404 : : /*
1405 : : * USB protocol requires resetting the data toggle for bulk
1406 : : * and interrupt endpoints when a CLEAR_FEATURE(ENDPOINT_HALT)
1407 : : * setup command is issued to the endpoint. Anticipate the
1408 : : * CLEAR_FEATURE command since a STALL has occurred and reset
1409 : : * the data toggle now.
1410 : : */
1411 : 0 : hc->qh->data_toggle = 0;
1412 : : }
1413 : :
1414 : 207 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_STALL);
1415 : :
1416 : : handle_stall_done:
1417 : 207 : disable_hc_int(hc_regs, stall);
1418 : :
1419 : 207 : return 1;
1420 : : }
1421 : :
1422 : : /*
1423 : : * Updates the state of the URB when a transfer has been stopped due to an
1424 : : * abnormal condition before the transfer completes. Modifies the
1425 : : * actual_length field of the URB to reflect the number of bytes that have
1426 : : * actually been transferred via the host channel.
1427 : : */
1428 : 0 : static void update_urb_state_xfer_intr(dwc_hc_t * hc,
1429 : : dwc_otg_hc_regs_t * hc_regs,
1430 : : dwc_otg_hcd_urb_t * urb,
1431 : : dwc_otg_qtd_t * qtd,
1432 : : dwc_otg_halt_status_e halt_status)
1433 : : {
1434 : 0 : uint32_t bytes_transferred = get_actual_xfer_length(hc, hc_regs, qtd,
1435 : : halt_status, NULL);
1436 : :
1437 [ # # ]: 0 : if (urb->actual_length + bytes_transferred > urb->length) {
1438 [ # # ]: 0 : printk_once(KERN_DEBUG "dwc_otg: DEVICE:%03d : %s:%d:trimming xfer length\n",
1439 : : hc->dev_addr, __func__, __LINE__);
1440 : 0 : bytes_transferred = urb->length - urb->actual_length;
1441 : : }
1442 : :
1443 : : /* non DWORD-aligned buffer case handling. */
1444 [ # # # # : 0 : if (hc->align_buff && bytes_transferred && hc->ep_is_in) {
# # ]
1445 : 0 : dwc_memcpy(urb->buf + urb->actual_length, hc->qh->dw_align_buf,
1446 : : bytes_transferred);
1447 : : }
1448 : :
1449 : 0 : urb->actual_length += bytes_transferred;
1450 : :
1451 : : #ifdef DEBUG
1452 : : {
1453 : : hctsiz_data_t hctsiz;
1454 : : hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
1455 : : DWC_DEBUGPL(DBG_HCDV, "DWC_otg: %s: %s, channel %d\n",
1456 : : __func__, (hc->ep_is_in ? "IN" : "OUT"),
1457 : : hc->hc_num);
1458 : : DWC_DEBUGPL(DBG_HCDV, " hc->start_pkt_count %d\n",
1459 : : hc->start_pkt_count);
1460 : : DWC_DEBUGPL(DBG_HCDV, " hctsiz.pktcnt %d\n", hctsiz.b.pktcnt);
1461 : : DWC_DEBUGPL(DBG_HCDV, " hc->max_packet %d\n", hc->max_packet);
1462 : : DWC_DEBUGPL(DBG_HCDV, " bytes_transferred %d\n",
1463 : : bytes_transferred);
1464 : : DWC_DEBUGPL(DBG_HCDV, " urb->actual_length %d\n",
1465 : : urb->actual_length);
1466 : : DWC_DEBUGPL(DBG_HCDV, " urb->transfer_buffer_length %d\n",
1467 : : urb->length);
1468 : : }
1469 : : #endif
1470 : 0 : }
1471 : :
1472 : : /**
1473 : : * Handles a host channel NAK interrupt. This handler may be called in either
1474 : : * DMA mode or Slave mode.
1475 : : */
1476 : 6715468 : static int32_t handle_hc_nak_intr(dwc_otg_hcd_t * hcd,
1477 : : dwc_hc_t * hc,
1478 : : dwc_otg_hc_regs_t * hc_regs,
1479 : : dwc_otg_qtd_t * qtd)
1480 : : {
1481 : : DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
1482 : : "NAK Received--\n", hc->hc_num);
1483 : :
1484 : : /*
1485 : : * When we get bulk NAKs then remember this so we holdoff on this qh until
1486 : : * the beginning of the next frame
1487 : : */
1488 [ + + ]: 13430936 : switch(dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
1489 : : case UE_BULK:
1490 : : case UE_CONTROL:
1491 [ + - + - ]: 4718 : if (nak_holdoff && qtd->qh->do_split)
1492 : 4718 : hc->qh->nak_frame = dwc_otg_hcd_get_frame_number(hcd);
1493 : : }
1494 : :
1495 : : /*
1496 : : * Handle NAK for IN/OUT SSPLIT/CSPLIT transfers, bulk, control, and
1497 : : * interrupt. Re-start the SSPLIT transfer.
1498 : : */
1499 [ + + ]: 6715468 : if (hc->do_split) {
1500 [ - + ]: 4304669 : if (hc->complete_split) {
1501 : 0 : qtd->error_count = 0;
1502 : : }
1503 : 4304669 : qtd->complete_split = 0;
1504 : 4304669 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
1505 : 4304669 : goto handle_nak_done;
1506 : : }
1507 : :
1508 [ - + - ]: 4821598 : switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
1509 : : case UE_CONTROL:
1510 : : case UE_BULK:
1511 [ # # # # ]: 0 : if (hcd->core_if->dma_enable && hc->ep_is_in) {
1512 : : /*
1513 : : * NAK interrupts are enabled on bulk/control IN
1514 : : * transfers in DMA mode for the sole purpose of
1515 : : * resetting the error count after a transaction error
1516 : : * occurs. The core will continue transferring data.
1517 : : * Disable other interrupts unmasked for the same
1518 : : * reason.
1519 : : */
1520 : 0 : disable_hc_int(hc_regs, datatglerr);
1521 : 0 : disable_hc_int(hc_regs, ack);
1522 : 0 : qtd->error_count = 0;
1523 : 0 : goto handle_nak_done;
1524 : : }
1525 : :
1526 : : /*
1527 : : * NAK interrupts normally occur during OUT transfers in DMA
1528 : : * or Slave mode. For IN transfers, more requests will be
1529 : : * queued as request queue space is available.
1530 : : */
1531 : 0 : qtd->error_count = 0;
1532 : :
1533 [ # # ]: 0 : if (!hc->qh->ping_state) {
1534 : 0 : update_urb_state_xfer_intr(hc, hc_regs,
1535 : : qtd->urb, qtd,
1536 : : DWC_OTG_HC_XFER_NAK);
1537 : 0 : dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
1538 : :
1539 [ # # ]: 0 : if (hc->speed == DWC_OTG_EP_SPEED_HIGH)
1540 : 0 : hc->qh->ping_state = 1;
1541 : : }
1542 : :
1543 : : /*
1544 : : * Halt the channel so the transfer can be re-started from
1545 : : * the appropriate point or the PING protocol will
1546 : : * start/continue.
1547 : : */
1548 : 0 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
1549 : 0 : break;
1550 : : case UE_INTERRUPT:
1551 : 2410799 : qtd->error_count = 0;
1552 : 2410799 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NAK);
1553 : 2410799 : break;
1554 : : case UE_ISOCHRONOUS:
1555 : : /* Should never get called for isochronous transfers. */
1556 : : DWC_ASSERT(1, "NACK interrupt for ISOC transfer\n");
1557 : : break;
1558 : : }
1559 : :
1560 : : handle_nak_done:
1561 : 6715468 : disable_hc_int(hc_regs, nak);
1562 : :
1563 : 6715468 : return 1;
1564 : : }
1565 : :
1566 : : /**
1567 : : * Handles a host channel ACK interrupt. This interrupt is enabled when
1568 : : * performing the PING protocol in Slave mode, when errors occur during
1569 : : * either Slave mode or DMA mode, and during Start Split transactions.
1570 : : */
1571 : 0 : static int32_t handle_hc_ack_intr(dwc_otg_hcd_t * hcd,
1572 : : dwc_hc_t * hc,
1573 : : dwc_otg_hc_regs_t * hc_regs,
1574 : : dwc_otg_qtd_t * qtd)
1575 : : {
1576 : : DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
1577 : : "ACK Received--\n", hc->hc_num);
1578 : :
1579 [ # # ]: 0 : if (hc->do_split) {
1580 : : /*
1581 : : * Handle ACK on SSPLIT.
1582 : : * ACK should not occur in CSPLIT.
1583 : : */
1584 [ # # # # ]: 0 : if (!hc->ep_is_in && hc->data_pid_start != DWC_OTG_HC_PID_SETUP) {
1585 : 0 : qtd->ssplit_out_xfer_count = hc->xfer_len;
1586 : : }
1587 [ # # ]: 0 : if (!(hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in)) {
1588 : : /* Don't need complete for isochronous out transfers. */
1589 : 0 : qtd->complete_split = 1;
1590 : : }
1591 : :
1592 : : /* ISOC OUT */
1593 [ # # ]: 0 : if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
1594 [ # # # ]: 0 : switch (hc->xact_pos) {
1595 : : case DWC_HCSPLIT_XACTPOS_ALL:
1596 : : break;
1597 : : case DWC_HCSPLIT_XACTPOS_END:
1598 : 0 : qtd->isoc_split_pos = DWC_HCSPLIT_XACTPOS_ALL;
1599 : 0 : qtd->isoc_split_offset = 0;
1600 : 0 : break;
1601 : : case DWC_HCSPLIT_XACTPOS_BEGIN:
1602 : : case DWC_HCSPLIT_XACTPOS_MID:
1603 : : /*
1604 : : * For BEGIN or MID, calculate the length for
1605 : : * the next microframe to determine the correct
1606 : : * SSPLIT token, either MID or END.
1607 : : */
1608 : : {
1609 : : struct dwc_otg_hcd_iso_packet_desc
1610 : : *frame_desc;
1611 : :
1612 : : frame_desc =
1613 : 0 : &qtd->urb->
1614 : 0 : iso_descs[qtd->isoc_frame_index];
1615 : 0 : qtd->isoc_split_offset += 188;
1616 : :
1617 [ # # ]: 0 : if ((frame_desc->length -
1618 : : qtd->isoc_split_offset) <= 188) {
1619 : 0 : qtd->isoc_split_pos =
1620 : : DWC_HCSPLIT_XACTPOS_END;
1621 : : } else {
1622 : 0 : qtd->isoc_split_pos =
1623 : : DWC_HCSPLIT_XACTPOS_MID;
1624 : : }
1625 : :
1626 : : }
1627 : : break;
1628 : : }
1629 : : } else {
1630 : 0 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
1631 : : }
1632 : : } else {
1633 : : /*
1634 : : * An unmasked ACK on a non-split DMA transaction is
1635 : : * for the sole purpose of resetting error counts. Disable other
1636 : : * interrupts unmasked for the same reason.
1637 : : */
1638 [ # # ]: 0 : if(hcd->core_if->dma_enable) {
1639 : 0 : disable_hc_int(hc_regs, datatglerr);
1640 : 0 : disable_hc_int(hc_regs, nak);
1641 : : }
1642 : 0 : qtd->error_count = 0;
1643 : :
1644 [ # # ]: 0 : if (hc->qh->ping_state) {
1645 : 0 : hc->qh->ping_state = 0;
1646 : : /*
1647 : : * Halt the channel so the transfer can be re-started
1648 : : * from the appropriate point. This only happens in
1649 : : * Slave mode. In DMA mode, the ping_state is cleared
1650 : : * when the transfer is started because the core
1651 : : * automatically executes the PING, then the transfer.
1652 : : */
1653 : 0 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_ACK);
1654 : : }
1655 : : }
1656 : :
1657 : : /*
1658 : : * If the ACK occurred when _not_ in the PING state, let the channel
1659 : : * continue transferring data after clearing the error count.
1660 : : */
1661 : :
1662 : 0 : disable_hc_int(hc_regs, ack);
1663 : :
1664 : 0 : return 1;
1665 : : }
1666 : :
1667 : : /**
1668 : : * Handles a host channel NYET interrupt. This interrupt should only occur on
1669 : : * Bulk and Control OUT endpoints and for complete split transactions. If a
1670 : : * NYET occurs at the same time as a Transfer Complete interrupt, it is
1671 : : * handled in the xfercomp interrupt handler, not here. This handler may be
1672 : : * called in either DMA mode or Slave mode.
1673 : : */
1674 : 0 : static int32_t handle_hc_nyet_intr(dwc_otg_hcd_t * hcd,
1675 : : dwc_hc_t * hc,
1676 : : dwc_otg_hc_regs_t * hc_regs,
1677 : : dwc_otg_qtd_t * qtd)
1678 : : {
1679 : : DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
1680 : : "NYET Received--\n", hc->hc_num);
1681 : :
1682 : : /*
1683 : : * NYET on CSPLIT
1684 : : * re-do the CSPLIT immediately on non-periodic
1685 : : */
1686 [ # # # # ]: 0 : if (hc->do_split && hc->complete_split) {
1687 [ # # ]: 0 : if (hc->ep_is_in && (hc->ep_type == DWC_OTG_EP_TYPE_ISOC)
1688 [ # # ]: 0 : && hcd->core_if->dma_enable) {
1689 : 0 : qtd->complete_split = 0;
1690 : 0 : qtd->isoc_split_offset = 0;
1691 [ # # ]: 0 : if (++qtd->isoc_frame_index == qtd->urb->packet_count) {
1692 : 0 : hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
1693 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
1694 : : }
1695 : : else
1696 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
1697 : : goto handle_nyet_done;
1698 : : }
1699 : :
1700 [ # # ]: 0 : if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
1701 : : hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
1702 : 0 : int frnum = dwc_otg_hcd_get_frame_number(hcd);
1703 : :
1704 : : // With the FIQ running we only ever see the failed NYET
1705 [ # # ]: 0 : if (dwc_full_frame_num(frnum) !=
1706 [ # # ]: 0 : dwc_full_frame_num(hc->qh->sched_frame) ||
1707 : : fiq_fsm_enable) {
1708 : : /*
1709 : : * No longer in the same full speed frame.
1710 : : * Treat this as a transaction error.
1711 : : */
1712 : : #if 0
1713 : : /** @todo Fix system performance so this can
1714 : : * be treated as an error. Right now complete
1715 : : * splits cannot be scheduled precisely enough
1716 : : * due to other system activity, so this error
1717 : : * occurs regularly in Slave mode.
1718 : : */
1719 : : qtd->error_count++;
1720 : : #endif
1721 : 0 : qtd->complete_split = 0;
1722 : 0 : halt_channel(hcd, hc, qtd,
1723 : : DWC_OTG_HC_XFER_XACT_ERR);
1724 : : /** @todo add support for isoc release */
1725 : 0 : goto handle_nyet_done;
1726 : : }
1727 : : }
1728 : :
1729 : 0 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
1730 : 0 : goto handle_nyet_done;
1731 : : }
1732 : :
1733 : 0 : hc->qh->ping_state = 1;
1734 : 0 : qtd->error_count = 0;
1735 : :
1736 : 0 : update_urb_state_xfer_intr(hc, hc_regs, qtd->urb, qtd,
1737 : : DWC_OTG_HC_XFER_NYET);
1738 : 0 : dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
1739 : :
1740 : : /*
1741 : : * Halt the channel and re-start the transfer so the PING
1742 : : * protocol will start.
1743 : : */
1744 : 0 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NYET);
1745 : :
1746 : : handle_nyet_done:
1747 : 0 : disable_hc_int(hc_regs, nyet);
1748 : 0 : return 1;
1749 : : }
1750 : :
1751 : : /**
1752 : : * Handles a host channel babble interrupt. This handler may be called in
1753 : : * either DMA mode or Slave mode.
1754 : : */
1755 : 0 : static int32_t handle_hc_babble_intr(dwc_otg_hcd_t * hcd,
1756 : : dwc_hc_t * hc,
1757 : : dwc_otg_hc_regs_t * hc_regs,
1758 : : dwc_otg_qtd_t * qtd)
1759 : : {
1760 : : DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
1761 : : "Babble Error--\n", hc->hc_num);
1762 : :
1763 [ # # ]: 0 : if (hcd->core_if->dma_desc_enable) {
1764 : 0 : dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
1765 : : DWC_OTG_HC_XFER_BABBLE_ERR);
1766 : 0 : goto handle_babble_done;
1767 : : }
1768 : :
1769 [ # # ]: 0 : if (hc->ep_type != DWC_OTG_EP_TYPE_ISOC) {
1770 : 0 : hcd->fops->complete(hcd, qtd->urb->priv,
1771 : : qtd->urb, -DWC_E_OVERFLOW);
1772 : 0 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_BABBLE_ERR);
1773 : : } else {
1774 : : dwc_otg_halt_status_e halt_status;
1775 : 0 : halt_status = update_isoc_urb_state(hcd, hc, hc_regs, qtd,
1776 : : DWC_OTG_HC_XFER_BABBLE_ERR);
1777 : 0 : halt_channel(hcd, hc, qtd, halt_status);
1778 : : }
1779 : :
1780 : : handle_babble_done:
1781 : 0 : disable_hc_int(hc_regs, bblerr);
1782 : 0 : return 1;
1783 : : }
1784 : :
1785 : : /**
1786 : : * Handles a host channel AHB error interrupt. This handler is only called in
1787 : : * DMA mode.
1788 : : */
1789 : 0 : static int32_t handle_hc_ahberr_intr(dwc_otg_hcd_t * hcd,
1790 : : dwc_hc_t * hc,
1791 : : dwc_otg_hc_regs_t * hc_regs,
1792 : : dwc_otg_qtd_t * qtd)
1793 : : {
1794 : : hcchar_data_t hcchar;
1795 : : hcsplt_data_t hcsplt;
1796 : : hctsiz_data_t hctsiz;
1797 : : uint32_t hcdma;
1798 : : char *pipetype, *speed;
1799 : :
1800 : 0 : dwc_otg_hcd_urb_t *urb = qtd->urb;
1801 : :
1802 : : DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
1803 : : "AHB Error--\n", hc->hc_num);
1804 : :
1805 : 0 : hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
1806 : 0 : hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
1807 : 0 : hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
1808 : 0 : hcdma = DWC_READ_REG32(&hc_regs->hcdma);
1809 : :
1810 : 0 : DWC_ERROR("AHB ERROR, Channel %d\n", hc->hc_num);
1811 : 0 : DWC_ERROR(" hcchar 0x%08x, hcsplt 0x%08x\n", hcchar.d32, hcsplt.d32);
1812 : 0 : DWC_ERROR(" hctsiz 0x%08x, hcdma 0x%08x\n", hctsiz.d32, hcdma);
1813 : : DWC_DEBUGPL(DBG_HCD, "DWC OTG HCD URB Enqueue\n");
1814 : 0 : DWC_ERROR(" Device address: %d\n",
1815 : : dwc_otg_hcd_get_dev_addr(&urb->pipe_info));
1816 [ # # ]: 0 : DWC_ERROR(" Endpoint: %d, %s\n",
1817 : : dwc_otg_hcd_get_ep_num(&urb->pipe_info),
1818 : : (dwc_otg_hcd_is_pipe_in(&urb->pipe_info) ? "IN" : "OUT"));
1819 : :
1820 : : switch (dwc_otg_hcd_get_pipe_type(&urb->pipe_info)) {
1821 : : case UE_CONTROL:
1822 : : pipetype = "CONTROL";
1823 : : break;
1824 : : case UE_BULK:
1825 : : pipetype = "BULK";
1826 : : break;
1827 : : case UE_INTERRUPT:
1828 : : pipetype = "INTERRUPT";
1829 : : break;
1830 : : case UE_ISOCHRONOUS:
1831 : : pipetype = "ISOCHRONOUS";
1832 : : break;
1833 : : default:
1834 : : pipetype = "UNKNOWN";
1835 : : break;
1836 : : }
1837 : :
1838 : 0 : DWC_ERROR(" Endpoint type: %s\n", pipetype);
1839 : :
1840 [ # # ]: 0 : switch (hc->speed) {
1841 : : case DWC_OTG_EP_SPEED_HIGH:
1842 : : speed = "HIGH";
1843 : : break;
1844 : : case DWC_OTG_EP_SPEED_FULL:
1845 : : speed = "FULL";
1846 : : break;
1847 : : case DWC_OTG_EP_SPEED_LOW:
1848 : : speed = "LOW";
1849 : : break;
1850 : : default:
1851 : : speed = "UNKNOWN";
1852 : : break;
1853 : : };
1854 : :
1855 : 0 : DWC_ERROR(" Speed: %s\n", speed);
1856 : :
1857 : 0 : DWC_ERROR(" Max packet size: %d\n",
1858 : : dwc_otg_hcd_get_mps(&urb->pipe_info));
1859 : 0 : DWC_ERROR(" Data buffer length: %d\n", urb->length);
1860 : 0 : DWC_ERROR(" Transfer buffer: %p, Transfer DMA: %p\n",
1861 : : urb->buf, (void *)urb->dma);
1862 : 0 : DWC_ERROR(" Setup buffer: %p, Setup DMA: %p\n",
1863 : : urb->setup_packet, (void *)urb->setup_dma);
1864 : 0 : DWC_ERROR(" Interval: %d\n", urb->interval);
1865 : :
1866 : : /* Core haltes the channel for Descriptor DMA mode */
1867 [ # # ]: 0 : if (hcd->core_if->dma_desc_enable) {
1868 : 0 : dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
1869 : : DWC_OTG_HC_XFER_AHB_ERR);
1870 : 0 : goto handle_ahberr_done;
1871 : : }
1872 : :
1873 : 0 : hcd->fops->complete(hcd, urb->priv, urb, -DWC_E_IO);
1874 : :
1875 : : /*
1876 : : * Force a channel halt. Don't call halt_channel because that won't
1877 : : * write to the HCCHARn register in DMA mode to force the halt.
1878 : : */
1879 : 0 : dwc_otg_hc_halt(hcd->core_if, hc, DWC_OTG_HC_XFER_AHB_ERR);
1880 : : handle_ahberr_done:
1881 : 0 : disable_hc_int(hc_regs, ahberr);
1882 : 0 : return 1;
1883 : : }
1884 : :
1885 : : /**
1886 : : * Handles a host channel transaction error interrupt. This handler may be
1887 : : * called in either DMA mode or Slave mode.
1888 : : */
1889 : 0 : static int32_t handle_hc_xacterr_intr(dwc_otg_hcd_t * hcd,
1890 : : dwc_hc_t * hc,
1891 : : dwc_otg_hc_regs_t * hc_regs,
1892 : : dwc_otg_qtd_t * qtd)
1893 : : {
1894 : : DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
1895 : : "Transaction Error--\n", hc->hc_num);
1896 : :
1897 [ # # ]: 0 : if (hcd->core_if->dma_desc_enable) {
1898 : 0 : dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
1899 : : DWC_OTG_HC_XFER_XACT_ERR);
1900 : 0 : goto handle_xacterr_done;
1901 : : }
1902 : :
1903 [ # # # # ]: 0 : switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
1904 : : case UE_CONTROL:
1905 : : case UE_BULK:
1906 : 0 : qtd->error_count++;
1907 [ # # ]: 0 : if (!hc->qh->ping_state) {
1908 : :
1909 : 0 : update_urb_state_xfer_intr(hc, hc_regs,
1910 : : qtd->urb, qtd,
1911 : : DWC_OTG_HC_XFER_XACT_ERR);
1912 : 0 : dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
1913 [ # # ]: 0 : if (!hc->ep_is_in && hc->speed == DWC_OTG_EP_SPEED_HIGH) {
1914 : 0 : hc->qh->ping_state = 1;
1915 : : }
1916 : : }
1917 : :
1918 : : /*
1919 : : * Halt the channel so the transfer can be re-started from
1920 : : * the appropriate point or the PING protocol will start.
1921 : : */
1922 : 0 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
1923 : 0 : break;
1924 : : case UE_INTERRUPT:
1925 : 0 : qtd->error_count++;
1926 [ # # # # ]: 0 : if (hc->do_split && hc->complete_split) {
1927 : 0 : qtd->complete_split = 0;
1928 : : }
1929 : 0 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
1930 : 0 : break;
1931 : : case UE_ISOCHRONOUS:
1932 : : {
1933 : : dwc_otg_halt_status_e halt_status;
1934 : 0 : halt_status =
1935 : : update_isoc_urb_state(hcd, hc, hc_regs, qtd,
1936 : : DWC_OTG_HC_XFER_XACT_ERR);
1937 : :
1938 : 0 : halt_channel(hcd, hc, qtd, halt_status);
1939 : : }
1940 : 0 : break;
1941 : : }
1942 : : handle_xacterr_done:
1943 : 0 : disable_hc_int(hc_regs, xacterr);
1944 : :
1945 : 0 : return 1;
1946 : : }
1947 : :
1948 : : /**
1949 : : * Handles a host channel frame overrun interrupt. This handler may be called
1950 : : * in either DMA mode or Slave mode.
1951 : : */
1952 : 32213 : static int32_t handle_hc_frmovrun_intr(dwc_otg_hcd_t * hcd,
1953 : : dwc_hc_t * hc,
1954 : : dwc_otg_hc_regs_t * hc_regs,
1955 : : dwc_otg_qtd_t * qtd)
1956 : : {
1957 : : DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
1958 : : "Frame Overrun--\n", hc->hc_num);
1959 : :
1960 [ + - - ]: 64426 : switch (dwc_otg_hcd_get_pipe_type(&qtd->urb->pipe_info)) {
1961 : : case UE_CONTROL:
1962 : : case UE_BULK:
1963 : : break;
1964 : : case UE_INTERRUPT:
1965 : 32213 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_FRAME_OVERRUN);
1966 : 32213 : break;
1967 : : case UE_ISOCHRONOUS:
1968 : : {
1969 : : dwc_otg_halt_status_e halt_status;
1970 : 0 : halt_status =
1971 : : update_isoc_urb_state(hcd, hc, hc_regs, qtd,
1972 : : DWC_OTG_HC_XFER_FRAME_OVERRUN);
1973 : :
1974 : 0 : halt_channel(hcd, hc, qtd, halt_status);
1975 : : }
1976 : 0 : break;
1977 : : }
1978 : :
1979 : 32213 : disable_hc_int(hc_regs, frmovrun);
1980 : :
1981 : 32213 : return 1;
1982 : : }
1983 : :
1984 : : /**
1985 : : * Handles a host channel data toggle error interrupt. This handler may be
1986 : : * called in either DMA mode or Slave mode.
1987 : : */
1988 : 0 : static int32_t handle_hc_datatglerr_intr(dwc_otg_hcd_t * hcd,
1989 : : dwc_hc_t * hc,
1990 : : dwc_otg_hc_regs_t * hc_regs,
1991 : : dwc_otg_qtd_t * qtd)
1992 : : {
1993 : : DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
1994 : : "Data Toggle Error on %s transfer--\n",
1995 : : hc->hc_num, (hc->ep_is_in ? "IN" : "OUT"));
1996 : :
1997 : : /* Data toggles on split transactions cause the hc to halt.
1998 : : * restart transfer */
1999 [ # # ]: 0 : if(hc->qh->do_split)
2000 : : {
2001 : 0 : qtd->error_count++;
2002 : 0 : dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
2003 : 0 : update_urb_state_xfer_intr(hc, hc_regs,
2004 : 0 : qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2005 : 0 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2006 [ # # ]: 0 : } else if (hc->ep_is_in) {
2007 : : /* An unmasked data toggle error on a non-split DMA transaction is
2008 : : * for the sole purpose of resetting error counts. Disable other
2009 : : * interrupts unmasked for the same reason.
2010 : : */
2011 [ # # ]: 0 : if(hcd->core_if->dma_enable) {
2012 : 0 : disable_hc_int(hc_regs, ack);
2013 : 0 : disable_hc_int(hc_regs, nak);
2014 : : }
2015 : 0 : qtd->error_count = 0;
2016 : : }
2017 : :
2018 : 0 : disable_hc_int(hc_regs, datatglerr);
2019 : :
2020 : 0 : return 1;
2021 : : }
2022 : :
2023 : : #ifdef DEBUG
2024 : : /**
2025 : : * This function is for debug only. It checks that a valid halt status is set
2026 : : * and that HCCHARn.chdis is clear. If there's a problem, corrective action is
2027 : : * taken and a warning is issued.
2028 : : * @return 1 if halt status is ok, 0 otherwise.
2029 : : */
2030 : : static inline int halt_status_ok(dwc_otg_hcd_t * hcd,
2031 : : dwc_hc_t * hc,
2032 : : dwc_otg_hc_regs_t * hc_regs,
2033 : : dwc_otg_qtd_t * qtd)
2034 : : {
2035 : : hcchar_data_t hcchar;
2036 : : hctsiz_data_t hctsiz;
2037 : : hcint_data_t hcint;
2038 : : hcintmsk_data_t hcintmsk;
2039 : : hcsplt_data_t hcsplt;
2040 : :
2041 : : if (hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS) {
2042 : : /*
2043 : : * This code is here only as a check. This condition should
2044 : : * never happen. Ignore the halt if it does occur.
2045 : : */
2046 : : hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2047 : : hctsiz.d32 = DWC_READ_REG32(&hc_regs->hctsiz);
2048 : : hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2049 : : hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
2050 : : hcsplt.d32 = DWC_READ_REG32(&hc_regs->hcsplt);
2051 : : DWC_WARN
2052 : : ("%s: hc->halt_status == DWC_OTG_HC_XFER_NO_HALT_STATUS, "
2053 : : "channel %d, hcchar 0x%08x, hctsiz 0x%08x, "
2054 : : "hcint 0x%08x, hcintmsk 0x%08x, "
2055 : : "hcsplt 0x%08x, qtd->complete_split %d\n", __func__,
2056 : : hc->hc_num, hcchar.d32, hctsiz.d32, hcint.d32,
2057 : : hcintmsk.d32, hcsplt.d32, qtd->complete_split);
2058 : :
2059 : : DWC_WARN("%s: no halt status, channel %d, ignoring interrupt\n",
2060 : : __func__, hc->hc_num);
2061 : : DWC_WARN("\n");
2062 : : clear_hc_int(hc_regs, chhltd);
2063 : : return 0;
2064 : : }
2065 : :
2066 : : /*
2067 : : * This code is here only as a check. hcchar.chdis should
2068 : : * never be set when the halt interrupt occurs. Halt the
2069 : : * channel again if it does occur.
2070 : : */
2071 : : hcchar.d32 = DWC_READ_REG32(&hc_regs->hcchar);
2072 : : if (hcchar.b.chdis) {
2073 : : DWC_WARN("%s: hcchar.chdis set unexpectedly, "
2074 : : "hcchar 0x%08x, trying to halt again\n",
2075 : : __func__, hcchar.d32);
2076 : : clear_hc_int(hc_regs, chhltd);
2077 : : hc->halt_pending = 0;
2078 : : halt_channel(hcd, hc, qtd, hc->halt_status);
2079 : : return 0;
2080 : : }
2081 : :
2082 : : return 1;
2083 : : }
2084 : : #endif
2085 : :
2086 : : /**
2087 : : * Handles a host Channel Halted interrupt in DMA mode. This handler
2088 : : * determines the reason the channel halted and proceeds accordingly.
2089 : : */
2090 : 2741873 : static void handle_hc_chhltd_intr_dma(dwc_otg_hcd_t * hcd,
2091 : : dwc_hc_t * hc,
2092 : : dwc_otg_hc_regs_t * hc_regs,
2093 : : dwc_otg_qtd_t * qtd)
2094 : : {
2095 : : int out_nak_enh = 0;
2096 : : hcint_data_t hcint;
2097 : : hcintmsk_data_t hcintmsk;
2098 : : /* For core with OUT NAK enhancement, the flow for high-
2099 : : * speed CONTROL/BULK OUT is handled a little differently.
2100 : : */
2101 [ + - ]: 2741873 : if (hcd->core_if->snpsid >= OTG_CORE_REV_2_71a) {
2102 [ + + + - ]: 2937222 : if (hc->speed == DWC_OTG_EP_SPEED_HIGH && !hc->ep_is_in &&
2103 : 195349 : (hc->ep_type == DWC_OTG_EP_TYPE_CONTROL ||
2104 : : hc->ep_type == DWC_OTG_EP_TYPE_BULK)) {
2105 : : out_nak_enh = 1;
2106 : : }
2107 : : }
2108 : :
2109 [ + - - + ]: 2741873 : if (hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE ||
2110 : : (hc->halt_status == DWC_OTG_HC_XFER_AHB_ERR
2111 [ # # ]: 0 : && !hcd->core_if->dma_desc_enable)) {
2112 : : /*
2113 : : * Just release the channel. A dequeue can happen on a
2114 : : * transfer timeout. In the case of an AHB Error, the channel
2115 : : * was forced to halt because there's no way to gracefully
2116 : : * recover.
2117 : : */
2118 [ # # ]: 0 : if (hcd->core_if->dma_desc_enable)
2119 : 0 : dwc_otg_hcd_complete_xfer_ddma(hcd, hc, hc_regs,
2120 : : hc->halt_status);
2121 : : else
2122 : 0 : release_channel(hcd, hc, qtd, hc->halt_status);
2123 : 2741872 : return;
2124 : : }
2125 : :
2126 : : /* Read the HCINTn register to determine the cause for the halt. */
2127 : :
2128 : 2741873 : hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2129 : 2741873 : hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
2130 : :
2131 [ + + ]: 2741872 : if (hcint.b.xfercomp) {
2132 : : /** @todo This is here because of a possible hardware bug. Spec
2133 : : * says that on SPLIT-ISOC OUT transfers in DMA mode that a HALT
2134 : : * interrupt w/ACK bit set should occur, but I only see the
2135 : : * XFERCOMP bit, even with it masked out. This is a workaround
2136 : : * for that behavior. Should fix this when hardware is fixed.
2137 : : */
2138 [ - + ]: 298655 : if (hc->ep_type == DWC_OTG_EP_TYPE_ISOC && !hc->ep_is_in) {
2139 : 0 : handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
2140 : : }
2141 : 298655 : handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd);
2142 [ + + ]: 2443217 : } else if (hcint.b.stall) {
2143 : 207 : handle_hc_stall_intr(hcd, hc, hc_regs, qtd);
2144 [ - + # # ]: 2443010 : } else if (hcint.b.xacterr && !hcd->core_if->dma_desc_enable) {
2145 [ # # ]: 0 : if (out_nak_enh) {
2146 [ # # ]: 0 : if (hcint.b.nyet || hcint.b.nak || hcint.b.ack) {
2147 : : DWC_DEBUGPL(DBG_HCD, "XactErr with NYET/NAK/ACK\n");
2148 : 0 : qtd->error_count = 0;
2149 : : } else {
2150 : : DWC_DEBUGPL(DBG_HCD, "XactErr without NYET/NAK/ACK\n");
2151 : : }
2152 : : }
2153 : :
2154 : : /*
2155 : : * Must handle xacterr before nak or ack. Could get a xacterr
2156 : : * at the same time as either of these on a BULK/CONTROL OUT
2157 : : * that started with a PING. The xacterr takes precedence.
2158 : : */
2159 : 0 : handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
2160 [ - + # # ]: 2443010 : } else if (hcint.b.xcs_xact && hcd->core_if->dma_desc_enable) {
2161 : 0 : handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
2162 [ - + # # ]: 2443010 : } else if (hcint.b.ahberr && hcd->core_if->dma_desc_enable) {
2163 : 0 : handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
2164 [ - + ]: 2443010 : } else if (hcint.b.bblerr) {
2165 : 0 : handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
2166 [ + + ]: 2443010 : } else if (hcint.b.frmovrun) {
2167 : 32213 : handle_hc_frmovrun_intr(hcd, hc, hc_regs, qtd);
2168 [ - + ]: 2410797 : } else if (hcint.b.datatglerr) {
2169 : 0 : handle_hc_datatglerr_intr(hcd, hc, hc_regs, qtd);
2170 [ + - ]: 2410797 : } else if (!out_nak_enh) {
2171 [ - + ]: 2410797 : if (hcint.b.nyet) {
2172 : : /*
2173 : : * Must handle nyet before nak or ack. Could get a nyet at the
2174 : : * same time as either of those on a BULK/CONTROL OUT that
2175 : : * started with a PING. The nyet takes precedence.
2176 : : */
2177 : 0 : handle_hc_nyet_intr(hcd, hc, hc_regs, qtd);
2178 [ + - + - ]: 2410797 : } else if (hcint.b.nak && !hcintmsk.b.nak) {
2179 : : /*
2180 : : * If nak is not masked, it's because a non-split IN transfer
2181 : : * is in an error state. In that case, the nak is handled by
2182 : : * the nak interrupt handler, not here. Handle nak here for
2183 : : * BULK/CONTROL OUT transfers, which halt on a NAK to allow
2184 : : * rewinding the buffer pointer.
2185 : : */
2186 : 2410797 : handle_hc_nak_intr(hcd, hc, hc_regs, qtd);
2187 [ # # # # ]: 0 : } else if (hcint.b.ack && !hcintmsk.b.ack) {
2188 : : /*
2189 : : * If ack is not masked, it's because a non-split IN transfer
2190 : : * is in an error state. In that case, the ack is handled by
2191 : : * the ack interrupt handler, not here. Handle ack here for
2192 : : * split transfers. Start splits halt on ACK.
2193 : : */
2194 : 0 : handle_hc_ack_intr(hcd, hc, hc_regs, qtd);
2195 : : } else {
2196 [ # # ]: 0 : if (hc->ep_type == DWC_OTG_EP_TYPE_INTR ||
2197 : : hc->ep_type == DWC_OTG_EP_TYPE_ISOC) {
2198 : : /*
2199 : : * A periodic transfer halted with no other channel
2200 : : * interrupts set. Assume it was halted by the core
2201 : : * because it could not be completed in its scheduled
2202 : : * (micro)frame.
2203 : : */
2204 : : #ifdef DEBUG
2205 : : DWC_PRINTF
2206 : : ("%s: Halt channel %d (assume incomplete periodic transfer)\n",
2207 : : __func__, hc->hc_num);
2208 : : #endif
2209 : 0 : halt_channel(hcd, hc, qtd,
2210 : : DWC_OTG_HC_XFER_PERIODIC_INCOMPLETE);
2211 : : } else {
2212 : 0 : DWC_ERROR
2213 : : ("%s: Channel %d, DMA Mode -- ChHltd set, but reason "
2214 : : "for halting is unknown, hcint 0x%08x, intsts 0x%08x\n",
2215 : : __func__, hc->hc_num, hcint.d32,
2216 : : DWC_READ_REG32(&hcd->
2217 : : core_if->core_global_regs->
2218 : : gintsts));
2219 : : /* Failthrough: use 3-strikes rule */
2220 : 0 : qtd->error_count++;
2221 : 0 : dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
2222 : 0 : update_urb_state_xfer_intr(hc, hc_regs,
2223 : 0 : qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2224 : 0 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2225 : : }
2226 : :
2227 : : }
2228 : : } else {
2229 : 0 : DWC_PRINTF("NYET/NAK/ACK/other in non-error case, 0x%08x\n",
2230 : : hcint.d32);
2231 : : /* Failthrough: use 3-strikes rule */
2232 : 0 : qtd->error_count++;
2233 : 0 : dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
2234 : 0 : update_urb_state_xfer_intr(hc, hc_regs,
2235 : 0 : qtd->urb, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2236 : 0 : halt_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_XACT_ERR);
2237 : : }
2238 : : }
2239 : :
2240 : : /**
2241 : : * Handles a host channel Channel Halted interrupt.
2242 : : *
2243 : : * In slave mode, this handler is called only when the driver specifically
2244 : : * requests a halt. This occurs during handling other host channel interrupts
2245 : : * (e.g. nak, xacterr, stall, nyet, etc.).
2246 : : *
2247 : : * In DMA mode, this is the interrupt that occurs when the core has finished
2248 : : * processing a transfer on a channel. Other host channel interrupts (except
2249 : : * ahberr) are disabled in DMA mode.
2250 : : */
2251 : 2741872 : static int32_t handle_hc_chhltd_intr(dwc_otg_hcd_t * hcd,
2252 : : dwc_hc_t * hc,
2253 : : dwc_otg_hc_regs_t * hc_regs,
2254 : : dwc_otg_qtd_t * qtd)
2255 : : {
2256 : : DWC_DEBUGPL(DBG_HCDI, "--Host Channel %d Interrupt: "
2257 : : "Channel Halted--\n", hc->hc_num);
2258 : :
2259 [ + - ]: 2741872 : if (hcd->core_if->dma_enable) {
2260 : 2741872 : handle_hc_chhltd_intr_dma(hcd, hc, hc_regs, qtd);
2261 : : } else {
2262 : : #ifdef DEBUG
2263 : : if (!halt_status_ok(hcd, hc, hc_regs, qtd)) {
2264 : : return 1;
2265 : : }
2266 : : #endif
2267 : 0 : release_channel(hcd, hc, qtd, hc->halt_status);
2268 : : }
2269 : :
2270 : 2741872 : return 1;
2271 : : }
2272 : :
2273 : :
2274 : : /**
2275 : : * dwc_otg_fiq_unmangle_isoc() - Update the iso_frame_desc structure on
2276 : : * FIQ transfer completion
2277 : : * @hcd: Pointer to dwc_otg_hcd struct
2278 : : * @num: Host channel number
2279 : : *
2280 : : * 1. Un-mangle the status as recorded in each iso_frame_desc status
2281 : : * 2. Copy it from the dwc_otg_urb into the real URB
2282 : : */
2283 : 0 : void dwc_otg_fiq_unmangle_isoc(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, dwc_otg_qtd_t *qtd, uint32_t num)
2284 : : {
2285 : 0 : struct dwc_otg_hcd_urb *dwc_urb = qtd->urb;
2286 : 0 : int nr_frames = dwc_urb->packet_count;
2287 : : int i;
2288 : : hcint_data_t frame_hcint;
2289 : :
2290 [ # # ]: 0 : for (i = 0; i < nr_frames; i++) {
2291 : 0 : frame_hcint.d32 = dwc_urb->iso_descs[i].status;
2292 [ # # ]: 0 : if (frame_hcint.b.xfercomp) {
2293 : 0 : dwc_urb->iso_descs[i].status = 0;
2294 : 0 : dwc_urb->actual_length += dwc_urb->iso_descs[i].actual_length;
2295 [ # # ]: 0 : } else if (frame_hcint.b.frmovrun) {
2296 [ # # ]: 0 : if (qh->ep_is_in)
2297 : 0 : dwc_urb->iso_descs[i].status = -DWC_E_NO_STREAM_RES;
2298 : : else
2299 : 0 : dwc_urb->iso_descs[i].status = -DWC_E_COMMUNICATION;
2300 : 0 : dwc_urb->error_count++;
2301 : 0 : dwc_urb->iso_descs[i].actual_length = 0;
2302 [ # # ]: 0 : } else if (frame_hcint.b.xacterr) {
2303 : 0 : dwc_urb->iso_descs[i].status = -DWC_E_PROTOCOL;
2304 : 0 : dwc_urb->error_count++;
2305 : 0 : dwc_urb->iso_descs[i].actual_length = 0;
2306 [ # # ]: 0 : } else if (frame_hcint.b.bblerr) {
2307 : 0 : dwc_urb->iso_descs[i].status = -DWC_E_OVERFLOW;
2308 : 0 : dwc_urb->error_count++;
2309 : 0 : dwc_urb->iso_descs[i].actual_length = 0;
2310 : : } else {
2311 : : /* Something went wrong */
2312 : 0 : dwc_urb->iso_descs[i].status = -1;
2313 : 0 : dwc_urb->iso_descs[i].actual_length = 0;
2314 : 0 : dwc_urb->error_count++;
2315 : : }
2316 : : }
2317 : 0 : qh->sched_frame = dwc_frame_num_inc(qh->sched_frame, qh->interval * (nr_frames - 1));
2318 : :
2319 : : //printk_ratelimited(KERN_INFO "%s: HS isochronous of %d/%d frames with %d errors complete\n",
2320 : : // __FUNCTION__, i, dwc_urb->packet_count, dwc_urb->error_count);
2321 : 0 : }
2322 : :
2323 : : /**
2324 : : * dwc_otg_fiq_unsetup_per_dma() - Remove data from bounce buffers for split transactions
2325 : : * @hcd: Pointer to dwc_otg_hcd struct
2326 : : * @num: Host channel number
2327 : : *
2328 : : * Copies data from the FIQ bounce buffers into the URB's transfer buffer. Does not modify URB state.
2329 : : * Returns total length of data or -1 if the buffers were not used.
2330 : : *
2331 : : */
2332 : 0 : int dwc_otg_fiq_unsetup_per_dma(dwc_otg_hcd_t *hcd, dwc_otg_qh_t *qh, dwc_otg_qtd_t *qtd, uint32_t num)
2333 : : {
2334 : 0 : dwc_hc_t *hc = qh->channel;
2335 : 0 : struct fiq_dma_blob *blob = hcd->fiq_dmab;
2336 : 0 : struct fiq_channel_state *st = &hcd->fiq_state->channel[num];
2337 : : uint8_t *ptr = NULL;
2338 : : int index = 0, len = 0;
2339 : : int i = 0;
2340 [ # # ]: 0 : if (hc->ep_is_in) {
2341 : : /* Copy data out of the DMA bounce buffers to the URB's buffer.
2342 : : * The align_buf is ignored as this is ignored on FSM enqueue. */
2343 : 0 : ptr = qtd->urb->buf;
2344 [ # # ]: 0 : if (qh->ep_type == UE_ISOCHRONOUS) {
2345 : : /* Isoc IN transactions - grab the offset of the iso_frame_desc into the URB transfer buffer */
2346 : 0 : index = qtd->isoc_frame_index;
2347 : 0 : ptr += qtd->urb->iso_descs[index].offset;
2348 : : } else {
2349 : : /* Need to increment by actual_length for interrupt IN */
2350 : 0 : ptr += qtd->urb->actual_length;
2351 : : }
2352 : :
2353 [ # # ]: 0 : for (i = 0; i < st->dma_info.index; i++) {
2354 : 0 : len += st->dma_info.slot_len[i];
2355 : 0 : dwc_memcpy(ptr, &blob->channel[num].index[i].buf[0], st->dma_info.slot_len[i]);
2356 : 0 : ptr += st->dma_info.slot_len[i];
2357 : : }
2358 : 0 : return len;
2359 : : } else {
2360 : : /* OUT endpoints - nothing to do. */
2361 : : return -1;
2362 : : }
2363 : :
2364 : : }
2365 : : /**
2366 : : * dwc_otg_hcd_handle_hc_fsm() - handle an unmasked channel interrupt
2367 : : * from a channel handled in the FIQ
2368 : : * @hcd: Pointer to dwc_otg_hcd struct
2369 : : * @num: Host channel number
2370 : : *
2371 : : * If a host channel interrupt was received by the IRQ and this was a channel
2372 : : * used by the FIQ, the execution flow for transfer completion is substantially
2373 : : * different from the normal (messy) path. This function and its friends handles
2374 : : * channel cleanup and transaction completion from a FIQ transaction.
2375 : : */
2376 : 4332196 : void dwc_otg_hcd_handle_hc_fsm(dwc_otg_hcd_t *hcd, uint32_t num)
2377 : : {
2378 : 4332196 : struct fiq_channel_state *st = &hcd->fiq_state->channel[num];
2379 : 4332196 : dwc_hc_t *hc = hcd->hc_ptr_array[num];
2380 : : dwc_otg_qtd_t *qtd;
2381 : 4332196 : dwc_otg_hc_regs_t *hc_regs = hcd->core_if->host_if->hc_regs[num];
2382 : 4332196 : hcint_data_t hcint = hcd->fiq_state->channel[num].hcint_copy;
2383 : 4332196 : hctsiz_data_t hctsiz = hcd->fiq_state->channel[num].hctsiz_copy;
2384 : : int hostchannels = 0;
2385 : : fiq_print(FIQDBG_INT, hcd->fiq_state, "OUT %01d %01d ", num , st->fsm);
2386 : :
2387 : : hostchannels = hcd->available_host_channels;
2388 [ - + ]: 4332196 : if (hc->halt_pending) {
2389 : : /* Dequeue: The FIQ was allowed to complete the transfer but state has been cleared. */
2390 [ # # # # : 0 : if (hc->qh && st->fsm == FIQ_NP_SPLIT_DONE &&
# # ]
2391 [ # # ]: 0 : hcint.b.xfercomp && hc->qh->ep_type == UE_BULK) {
2392 [ # # ]: 0 : if (hctsiz.b.pid == DWC_HCTSIZ_DATA0) {
2393 : 0 : hc->qh->data_toggle = DWC_OTG_HC_PID_DATA1;
2394 : : } else {
2395 : 0 : hc->qh->data_toggle = DWC_OTG_HC_PID_DATA0;
2396 : : }
2397 : : }
2398 : 0 : release_channel(hcd, hc, NULL, hc->halt_status);
2399 : 0 : return;
2400 : : }
2401 : :
2402 : 4332196 : qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
2403 [ - + - - : 4332196 : switch (st->fsm) {
- - - - -
- - - - ]
2404 : : case FIQ_TEST:
2405 : : break;
2406 : :
2407 : : case FIQ_DEQUEUE_ISSUED:
2408 : : /* Handled above, but keep for posterity */
2409 : 0 : release_channel(hcd, hc, NULL, hc->halt_status);
2410 : 0 : break;
2411 : :
2412 : : case FIQ_NP_SPLIT_DONE:
2413 : : /* Nonperiodic transaction complete. */
2414 [ + + ]: 4332196 : if (!hc->ep_is_in) {
2415 : 10179 : qtd->ssplit_out_xfer_count = hc->xfer_len;
2416 : : }
2417 [ + + ]: 4332196 : if (hcint.b.xfercomp) {
2418 : 27533 : handle_hc_xfercomp_intr(hcd, hc, hc_regs, qtd);
2419 [ + - ]: 4304663 : } else if (hcint.b.nak) {
2420 : 4304663 : handle_hc_nak_intr(hcd, hc, hc_regs, qtd);
2421 : : } else {
2422 : 0 : DWC_WARN("Unexpected IRQ state on FSM transaction:"
2423 : : "dev_addr=%d ep=%d fsm=%d, hcint=0x%08x\n",
2424 : : hc->dev_addr, hc->ep_num, st->fsm, hcint.d32);
2425 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
2426 : : }
2427 : : break;
2428 : :
2429 : : case FIQ_NP_SPLIT_HS_ABORTED:
2430 : : /* A HS abort is a 3-strikes on the HS bus at any point in the transaction.
2431 : : * Normally a CLEAR_TT_BUFFER hub command would be required: we can't do that
2432 : : * because there's no guarantee which order a non-periodic split happened in.
2433 : : * We could end up clearing a perfectly good transaction out of the buffer.
2434 : : */
2435 [ # # ]: 0 : if (hcint.b.xacterr) {
2436 : 0 : qtd->error_count += st->nr_errors;
2437 : 0 : handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
2438 [ # # ]: 0 : } else if (hcint.b.ahberr) {
2439 : 0 : handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
2440 : : } else {
2441 : 0 : DWC_WARN("Unexpected IRQ state on FSM transaction:"
2442 : : "dev_addr=%d ep=%d fsm=%d, hcint=0x%08x\n",
2443 : : hc->dev_addr, hc->ep_num, st->fsm, hcint.d32);
2444 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
2445 : : }
2446 : : break;
2447 : :
2448 : : case FIQ_NP_SPLIT_LS_ABORTED:
2449 : : /* A few cases can cause this - either an unknown state on a SSPLIT or
2450 : : * STALL/data toggle error response on a CSPLIT */
2451 [ # # ]: 0 : if (hcint.b.stall) {
2452 : 0 : handle_hc_stall_intr(hcd, hc, hc_regs, qtd);
2453 [ # # ]: 0 : } else if (hcint.b.datatglerr) {
2454 : 0 : handle_hc_datatglerr_intr(hcd, hc, hc_regs, qtd);
2455 [ # # ]: 0 : } else if (hcint.b.bblerr) {
2456 : 0 : handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
2457 [ # # ]: 0 : } else if (hcint.b.ahberr) {
2458 : 0 : handle_hc_ahberr_intr(hcd, hc, hc_regs, qtd);
2459 : : } else {
2460 : 0 : DWC_WARN("Unexpected IRQ state on FSM transaction:"
2461 : : "dev_addr=%d ep=%d fsm=%d, hcint=0x%08x\n",
2462 : : hc->dev_addr, hc->ep_num, st->fsm, hcint.d32);
2463 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
2464 : : }
2465 : : break;
2466 : :
2467 : : case FIQ_PER_SPLIT_DONE:
2468 : : /* Isoc IN or Interrupt IN/OUT */
2469 : :
2470 : : /* Flow control here is different from the normal execution by the driver.
2471 : : * We need to completely ignore most of the driver's method of handling
2472 : : * split transactions and do it ourselves.
2473 : : */
2474 [ # # ]: 0 : if (hc->ep_type == UE_INTERRUPT) {
2475 [ # # ]: 0 : if (hcint.b.nak) {
2476 : 0 : handle_hc_nak_intr(hcd, hc, hc_regs, qtd);
2477 [ # # ]: 0 : } else if (hc->ep_is_in) {
2478 : : int len;
2479 : 0 : len = dwc_otg_fiq_unsetup_per_dma(hcd, hc->qh, qtd, num);
2480 : : //printk(KERN_NOTICE "FIQ Transaction: hc=%d len=%d urb_len = %d\n", num, len, qtd->urb->length);
2481 : 0 : qtd->urb->actual_length += len;
2482 [ # # ]: 0 : if (qtd->urb->actual_length >= qtd->urb->length) {
2483 : 0 : qtd->urb->status = 0;
2484 : 0 : hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, qtd->urb->status);
2485 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
2486 : : } else {
2487 : : /* Interrupt transfer not complete yet - is it a short read? */
2488 [ # # ]: 0 : if (len < hc->max_packet) {
2489 : : /* Interrupt transaction complete */
2490 : 0 : qtd->urb->status = 0;
2491 : 0 : hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, qtd->urb->status);
2492 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
2493 : : } else {
2494 : : /* Further transactions required */
2495 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE);
2496 : : }
2497 : : }
2498 : : } else {
2499 : : /* Interrupt OUT complete. */
2500 : 0 : dwc_otg_hcd_save_data_toggle(hc, hc_regs, qtd);
2501 : 0 : qtd->urb->actual_length += hc->xfer_len;
2502 [ # # ]: 0 : if (qtd->urb->actual_length >= qtd->urb->length) {
2503 : 0 : qtd->urb->status = 0;
2504 : 0 : hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, qtd->urb->status);
2505 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
2506 : : } else {
2507 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE);
2508 : : }
2509 : : }
2510 : : } else {
2511 : : /* ISOC IN complete. */
2512 : 0 : struct dwc_otg_hcd_iso_packet_desc *frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
2513 : : int len = 0;
2514 : : /* Record errors, update qtd. */
2515 [ # # ]: 0 : if (st->nr_errors) {
2516 : 0 : frame_desc->actual_length = 0;
2517 : 0 : frame_desc->status = -DWC_E_PROTOCOL;
2518 : : } else {
2519 : 0 : frame_desc->status = 0;
2520 : : /* Unswizzle dma */
2521 : 0 : len = dwc_otg_fiq_unsetup_per_dma(hcd, hc->qh, qtd, num);
2522 : 0 : frame_desc->actual_length = len;
2523 : : }
2524 : 0 : qtd->isoc_frame_index++;
2525 [ # # ]: 0 : if (qtd->isoc_frame_index == qtd->urb->packet_count) {
2526 : 0 : hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
2527 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
2528 : : } else {
2529 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE);
2530 : : }
2531 : : }
2532 : : break;
2533 : :
2534 : : case FIQ_PER_ISO_OUT_DONE: {
2535 : 0 : struct dwc_otg_hcd_iso_packet_desc *frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
2536 : : /* Record errors, update qtd. */
2537 [ # # ]: 0 : if (st->nr_errors) {
2538 : 0 : frame_desc->actual_length = 0;
2539 : 0 : frame_desc->status = -DWC_E_PROTOCOL;
2540 : : } else {
2541 : 0 : frame_desc->status = 0;
2542 : 0 : frame_desc->actual_length = frame_desc->length;
2543 : : }
2544 : 0 : qtd->isoc_frame_index++;
2545 : 0 : qtd->isoc_split_offset = 0;
2546 [ # # ]: 0 : if (qtd->isoc_frame_index == qtd->urb->packet_count) {
2547 : 0 : hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
2548 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
2549 : : } else {
2550 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE);
2551 : : }
2552 : : }
2553 : : break;
2554 : :
2555 : : case FIQ_PER_SPLIT_NYET_ABORTED:
2556 : : /* Doh. lost the data. */
2557 [ # # ]: 0 : printk_ratelimited(KERN_INFO "Transfer to device %d endpoint 0x%x frame %d failed "
2558 : : "- FIQ reported NYET. Data may have been lost.\n",
2559 : : hc->dev_addr, hc->ep_num, dwc_otg_hcd_get_frame_number(hcd) >> 3);
2560 [ # # ]: 0 : if (hc->ep_type == UE_ISOCHRONOUS) {
2561 : 0 : struct dwc_otg_hcd_iso_packet_desc *frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
2562 : : /* Record errors, update qtd. */
2563 : 0 : frame_desc->actual_length = 0;
2564 : 0 : frame_desc->status = -DWC_E_PROTOCOL;
2565 : 0 : qtd->isoc_frame_index++;
2566 : 0 : qtd->isoc_split_offset = 0;
2567 [ # # ]: 0 : if (qtd->isoc_frame_index == qtd->urb->packet_count) {
2568 : 0 : hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
2569 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
2570 : : } else {
2571 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE);
2572 : : }
2573 : : } else {
2574 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
2575 : : }
2576 : : break;
2577 : :
2578 : : case FIQ_HS_ISOC_DONE:
2579 : : /* The FIQ has performed a whole pile of isochronous transactions.
2580 : : * The status is recorded as the interrupt state should the transaction
2581 : : * fail.
2582 : : */
2583 : 0 : dwc_otg_fiq_unmangle_isoc(hcd, hc->qh, qtd, num);
2584 : 0 : hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
2585 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
2586 : 0 : break;
2587 : :
2588 : : case FIQ_PER_SPLIT_LS_ABORTED:
2589 [ # # ]: 0 : if (hcint.b.xacterr) {
2590 : : /* Hub has responded with an ERR packet. Device
2591 : : * has been unplugged or the port has been disabled.
2592 : : * TODO: need to issue a reset to the hub port. */
2593 : 0 : qtd->error_count += 3;
2594 : 0 : handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
2595 [ # # ]: 0 : } else if (hcint.b.stall) {
2596 : 0 : handle_hc_stall_intr(hcd, hc, hc_regs, qtd);
2597 [ # # ]: 0 : } else if (hcint.b.bblerr) {
2598 : 0 : handle_hc_babble_intr(hcd, hc, hc_regs, qtd);
2599 : : } else {
2600 [ # # ]: 0 : printk_ratelimited(KERN_INFO "Transfer to device %d endpoint 0x%x failed "
2601 : : "- FIQ reported FSM=%d. Data may have been lost.\n",
2602 : : st->fsm, hc->dev_addr, hc->ep_num);
2603 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
2604 : : }
2605 : : break;
2606 : :
2607 : : case FIQ_PER_SPLIT_HS_ABORTED:
2608 : : /* Either the SSPLIT phase suffered transaction errors or something
2609 : : * unexpected happened.
2610 : : */
2611 : 0 : qtd->error_count += 3;
2612 : 0 : handle_hc_xacterr_intr(hcd, hc, hc_regs, qtd);
2613 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
2614 : 0 : break;
2615 : :
2616 : : case FIQ_PER_SPLIT_TIMEOUT:
2617 : : /* Couldn't complete in the nominated frame */
2618 : 0 : printk(KERN_INFO "Transfer to device %d endpoint 0x%x frame %d failed "
2619 : : "- FIQ timed out. Data may have been lost.\n",
2620 : 0 : hc->dev_addr, hc->ep_num, dwc_otg_hcd_get_frame_number(hcd) >> 3);
2621 [ # # ]: 0 : if (hc->ep_type == UE_ISOCHRONOUS) {
2622 : 0 : struct dwc_otg_hcd_iso_packet_desc *frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index];
2623 : : /* Record errors, update qtd. */
2624 : 0 : frame_desc->actual_length = 0;
2625 [ # # ]: 0 : if (hc->ep_is_in) {
2626 : 0 : frame_desc->status = -DWC_E_NO_STREAM_RES;
2627 : : } else {
2628 : 0 : frame_desc->status = -DWC_E_COMMUNICATION;
2629 : : }
2630 : 0 : qtd->isoc_frame_index++;
2631 [ # # ]: 0 : if (qtd->isoc_frame_index == qtd->urb->packet_count) {
2632 : 0 : hcd->fops->complete(hcd, qtd->urb->priv, qtd->urb, 0);
2633 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_URB_COMPLETE);
2634 : : } else {
2635 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_COMPLETE);
2636 : : }
2637 : : } else {
2638 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
2639 : : }
2640 : : break;
2641 : :
2642 : : default:
2643 : 0 : DWC_WARN("Unexpected state received on hc=%d fsm=%d on transfer to device %d ep 0x%x",
2644 : : hc->hc_num, st->fsm, hc->dev_addr, hc->ep_num);
2645 : 0 : qtd->error_count++;
2646 : 0 : release_channel(hcd, hc, qtd, DWC_OTG_HC_XFER_NO_HALT_STATUS);
2647 : : }
2648 : : return;
2649 : : }
2650 : :
2651 : : /** Handles interrupt for a specific Host Channel */
2652 : 7080584 : int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num)
2653 : : {
2654 : : int retval = 0;
2655 : : hcint_data_t hcint;
2656 : : hcintmsk_data_t hcintmsk;
2657 : : dwc_hc_t *hc;
2658 : : dwc_otg_hc_regs_t *hc_regs;
2659 : : dwc_otg_qtd_t *qtd;
2660 : :
2661 : : DWC_DEBUGPL(DBG_HCDV, "--Host Channel Interrupt--, Channel %d\n", num);
2662 : :
2663 : 7080584 : hc = dwc_otg_hcd->hc_ptr_array[num];
2664 : 7080584 : hc_regs = dwc_otg_hcd->core_if->host_if->hc_regs[num];
2665 [ + + ]: 7080584 : if(hc->halt_status == DWC_OTG_HC_XFER_URB_DEQUEUE) {
2666 : : /* A dequeue was issued for this transfer. Our QTD has gone away
2667 : : * but in the case of a FIQ transfer, the transfer would have run
2668 : : * to completion.
2669 : : */
2670 [ + - - + ]: 6516 : if (fiq_fsm_enable && dwc_otg_hcd->fiq_state->channel[num].fsm != FIQ_PASSTHROUGH) {
2671 : 0 : dwc_otg_hcd_handle_hc_fsm(dwc_otg_hcd, num);
2672 : : } else {
2673 : 6516 : release_channel(dwc_otg_hcd, hc, NULL, hc->halt_status);
2674 : : }
2675 : : return 1;
2676 : : }
2677 : 7074068 : qtd = DWC_CIRCLEQ_FIRST(&hc->qh->qtd_list);
2678 : :
2679 : : /*
2680 : : * FSM mode: Check to see if this is a HC interrupt from a channel handled by the FIQ.
2681 : : * Execution path is fundamentally different for the channels after a FIQ has completed
2682 : : * a split transaction.
2683 : : */
2684 [ + - ]: 7074068 : if (fiq_fsm_enable) {
2685 [ - + + ]: 7074068 : switch (dwc_otg_hcd->fiq_state->channel[num].fsm) {
2686 : : case FIQ_PASSTHROUGH:
2687 : : break;
2688 : : case FIQ_PASSTHROUGH_ERRORSTATE:
2689 : : /* Hook into the error count */
2690 : : fiq_print(FIQDBG_ERR, dwc_otg_hcd->fiq_state, "HCDERR%02d", num);
2691 [ # # ]: 0 : if (!dwc_otg_hcd->fiq_state->channel[num].nr_errors) {
2692 : 0 : qtd->error_count = 0;
2693 : : fiq_print(FIQDBG_ERR, dwc_otg_hcd->fiq_state, "RESET ");
2694 : : }
2695 : : break;
2696 : : default:
2697 : 4332196 : dwc_otg_hcd_handle_hc_fsm(dwc_otg_hcd, num);
2698 : 4332195 : return 1;
2699 : : }
2700 : : }
2701 : :
2702 : 2741872 : hcint.d32 = DWC_READ_REG32(&hc_regs->hcint);
2703 : 2741872 : hcintmsk.d32 = DWC_READ_REG32(&hc_regs->hcintmsk);
2704 : 2741872 : hcint.d32 = hcint.d32 & hcintmsk.d32;
2705 [ - + ]: 2741872 : if (!dwc_otg_hcd->core_if->dma_enable) {
2706 [ # # # # ]: 0 : if (hcint.b.chhltd && hcint.d32 != 0x2) {
2707 : 0 : hcint.b.chhltd = 0;
2708 : : }
2709 : : }
2710 : :
2711 [ - + ]: 2741872 : if (hcint.b.xfercomp) {
2712 : : retval |=
2713 : 0 : handle_hc_xfercomp_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2714 : : /*
2715 : : * If NYET occurred at same time as Xfer Complete, the NYET is
2716 : : * handled by the Xfer Complete interrupt handler. Don't want
2717 : : * to call the NYET interrupt handler in this case.
2718 : : */
2719 : 0 : hcint.b.nyet = 0;
2720 : : }
2721 [ + - ]: 2741872 : if (hcint.b.chhltd) {
2722 : 2741872 : retval |= handle_hc_chhltd_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2723 : : }
2724 [ - + ]: 2741872 : if (hcint.b.ahberr) {
2725 : 0 : retval |= handle_hc_ahberr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2726 : : }
2727 [ - + ]: 2741872 : if (hcint.b.stall) {
2728 : 0 : retval |= handle_hc_stall_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2729 : : }
2730 [ - + ]: 2741872 : if (hcint.b.nak) {
2731 : 0 : retval |= handle_hc_nak_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2732 : : }
2733 [ - + ]: 2741872 : if (hcint.b.ack) {
2734 [ # # ]: 0 : if(!hcint.b.chhltd)
2735 : 0 : retval |= handle_hc_ack_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2736 : : }
2737 [ - + ]: 2741872 : if (hcint.b.nyet) {
2738 : 0 : retval |= handle_hc_nyet_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2739 : : }
2740 [ - + ]: 2741872 : if (hcint.b.xacterr) {
2741 : 0 : retval |= handle_hc_xacterr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2742 : : }
2743 [ - + ]: 2741872 : if (hcint.b.bblerr) {
2744 : 0 : retval |= handle_hc_babble_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2745 : : }
2746 [ - + ]: 2741872 : if (hcint.b.frmovrun) {
2747 : 0 : retval |=
2748 : 0 : handle_hc_frmovrun_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2749 : : }
2750 [ - + ]: 2741872 : if (hcint.b.datatglerr) {
2751 : 0 : retval |=
2752 : 0 : handle_hc_datatglerr_intr(dwc_otg_hcd, hc, hc_regs, qtd);
2753 : : }
2754 : :
2755 : 2741872 : return retval;
2756 : : }
2757 : : #endif /* DWC_DEVICE_ONLY */
|