From 3591adedd2b8fded3e5e3af389cce18e81593089 Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Wed, 9 Dec 2015 11:50:14 +0800 Subject: [PATCH 1/3] Revert "USB: Switch to NOP FIQ" This reverts commit 0ce082bce52cdcdb3d78cddf9d45f6957664a531. --- drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c | 2 +- drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c index af01a67e9ac9..9ac2a830045b 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_driver.c @@ -276,7 +276,7 @@ static const char *dma_config_name[] = { //Global variable to switch the fiq fix on or off bool fiq_enable = 1; // Global variable to enable the split transaction fix -bool fiq_fsm_enable = false; +bool fiq_fsm_enable = true; //Bulk split-transaction NAK holdoff in microframes uint16_t nak_holdoff = 8; diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c index 47231a5517a1..ea27c4c8f9d3 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c @@ -1293,16 +1293,17 @@ void notrace dwc_otg_fiq_nop(struct fiq_state *state) /* We got an interrupt, didn't handle it and want to mask it */ if (~(state->gintmsk_saved.d32)) { -// state->mphi_int_count++; + state->mphi_int_count++; gintmsk.d32 &= state->gintmsk_saved.d32; FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32); /* Force a clear before another dummy send */ -// FIQ_WRITE(state->mphi_regs.intstat, (1<<29)); -// FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send); -// FIQ_WRITE(state->mphi_regs.outddb, (1<<29)); - state->fiq_done++; - WRITE_CBUS_REG(ISA_TIMERD, 1); + FIQ_WRITE(state->mphi_regs.intstat, (1<<29)); + FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send); + FIQ_WRITE(state->mphi_regs.outddb, (1<<29)); + } + state->fiq_done++; + WRITE_CBUS_REG(ISA_TIMERD, 1); //mb(); } From 9abeb9953d36e6d613314f109c8915266fa16be4 Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Thu, 17 Dec 2015 17:34:09 +0800 Subject: [PATCH 2/3] remove mphi dependency --- .../amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c index ea27c4c8f9d3..c2cac24bc510 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c @@ -1227,15 +1227,8 @@ void notrace __dwc_otg_fiq_fsm(struct fiq_state *state, int num_channels) FIQ_WRITE(state->dwc_regs_base + GINTSTS, gintsts_handled.d32); } - /* We got an interrupt, didn't handle it. */ - //if (kick_irq) { - // state->mphi_int_count++; - // FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send); - // FIQ_WRITE(state->mphi_regs.outddb, (1<<29)); - - //} state->fiq_done++; - if (kick_irq) +// if (kick_irq) WRITE_CBUS_REG(ISA_TIMERD, 1); //mb(); } @@ -1293,17 +1286,12 @@ void notrace dwc_otg_fiq_nop(struct fiq_state *state) /* We got an interrupt, didn't handle it and want to mask it */ if (~(state->gintmsk_saved.d32)) { - state->mphi_int_count++; - gintmsk.d32 &= state->gintmsk_saved.d32; - FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32); - /* Force a clear before another dummy send */ - FIQ_WRITE(state->mphi_regs.intstat, (1<<29)); - FIQ_WRITE(state->mphi_regs.outdda, (int) state->dummy_send); - FIQ_WRITE(state->mphi_regs.outddb, (1<<29)); + gintmsk.d32 &= state->gintmsk_saved.d32; + FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32); + state->fiq_done++; + WRITE_CBUS_REG(ISA_TIMERD, 1); } - state->fiq_done++; - WRITE_CBUS_REG(ISA_TIMERD, 1); //mb(); } From 3965ecd6f9620bd5aec856274fb2ca7e448f9ffd Mon Sep 17 00:00:00 2001 From: Chris Chiu Date: Tue, 22 Dec 2015 21:43:51 +0800 Subject: [PATCH 3/3] re-enable haintmsk for the host channel which have finished last interrupt. This will avoid hc_xfer_timeout when multiple usb device access --- drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c | 15 +++++++++++---- drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.h | 1 + drivers/amlogic/usb/dwc_otg/310/dwc_otg_hcd.c | 2 ++ .../amlogic/usb/dwc_otg/310/dwc_otg_hcd_intr.c | 14 ++++++++++++-- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c index c2cac24bc510..5a3c82c69668 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.c @@ -1172,6 +1172,15 @@ void notrace __dwc_otg_fiq_fsm(struct fiq_state *state, int num_channels) int i; haint.d32 = FIQ_READ(state->dwc_regs_base + HAINT); haintmsk.d32 = FIQ_READ(state->dwc_regs_base + HAINTMSK); + + // check the host channel intr been handled or not. if yes, allow + // interrupt trigger. + for (i = 0; i < num_channels; i++) { + if (state->channel[i].hcint_handled) { + haintmsk.d32 |= (1 << i); + state->channel[i].hcint_handled = 0; + } + } haint.d32 &= haintmsk.d32; haint_handled.d32 = 0; for (i=0; idwc_regs_base + HAINTMSK, haintmsk.d32); kick_irq |= 1; } + /* Top-Level interrupt - always handled because it's level-sensitive */ gintsts_handled.b.hcintr = 1; } @@ -1216,9 +1226,6 @@ void notrace __dwc_otg_fiq_fsm(struct fiq_state *state, int num_channels) gintmsk.d32 &= state->gintmsk_saved.d32; gintmsk.b.sofintr = 1; FIQ_WRITE(state->dwc_regs_base + GINTMSK, gintmsk.d32); -// fiq_print(FIQDBG_INT, state, "KICKGINT"); -// fiq_print(FIQDBG_INT, state, "%08x", gintmsk.d32); -// fiq_print(FIQDBG_INT, state, "%08x", state->gintmsk_saved.d32); kick_irq |= 1; } @@ -1228,7 +1235,7 @@ void notrace __dwc_otg_fiq_fsm(struct fiq_state *state, int num_channels) } state->fiq_done++; -// if (kick_irq) + if (kick_irq) WRITE_CBUS_REG(ISA_TIMERD, 1); //mb(); } diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.h b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.h index f70660761e6b..f829f6ac5750 100644 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.h +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_fiq_fsm.h @@ -289,6 +289,7 @@ struct fiq_channel_state { unsigned int expected_uframe; /* in/out for communicating number of dma buffers used, or number of ISOC to do */ unsigned int nrpackets; + unsigned int hcint_handled; struct fiq_dma_info dma_info; struct fiq_hs_isoc_info hs_isoc_info; /* Copies of HC registers - in/out communication from/to IRQ handler diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_hcd.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_hcd.c index b787cf953050..c901cb18e8ca 100755 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_hcd.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_hcd.c @@ -1083,6 +1083,7 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) dwc_otg_hcd_free(hcd); goto out; } + memset(channel, 0, sizeof(dwc_hc_t)); channel->hc_num = i; hcd->hc_ptr_array[i] = channel; #ifdef DEBUG @@ -1106,6 +1107,7 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if) for (i = 0; i < num_channels; i++) { hcd->fiq_state->channel[i].fsm = FIQ_PASSTHROUGH; + hcd->fiq_state->channel[i].hcint_handled = 0; } hcd->fiq_state->dummy_send = DWC_ALLOC_ATOMIC(16); diff --git a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_hcd_intr.c b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_hcd_intr.c index 59a1ef591f13..8fe0fc540a8f 100755 --- a/drivers/amlogic/usb/dwc_otg/310/dwc_otg_hcd_intr.c +++ b/drivers/amlogic/usb/dwc_otg/310/dwc_otg_hcd_intr.c @@ -659,7 +659,17 @@ int32_t dwc_otg_hcd_handle_hc_intr(dwc_otg_hcd_t * dwc_otg_hcd) for (i = 0; i < dwc_otg_hcd->core_if->core_params->host_channels; i++) { if (haint.b2.chint & (1 << i)) { retval |= dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd, i); - } + + // inform fiq level to know the host channel interrupt been handled + // turn on the corresponding bit in haintmsk to allow next hw intr + if (fiq_fsm_enable&&dwc_otg_hcd->core_if->use_fiq_flag && + dwc_otg_hcd->hc_ptr_array[i]->ep_type == DWC_OTG_EP_TYPE_BULK && + dwc_otg_hcd->fiq_state->channel[i].fsm == FIQ_PASSTHROUGH) { + local_fiq_disable(); + dwc_otg_hcd->fiq_state->channel[i].hcint_handled = 1; + local_fiq_enable(); + } + } } return retval; @@ -2713,4 +2723,4 @@ int32_t dwc_otg_hcd_handle_hc_n_intr(dwc_otg_hcd_t * dwc_otg_hcd, uint32_t num) return retval; } -#endif /* DWC_DEVICE_ONLY */ \ No newline at end of file +#endif /* DWC_DEVICE_ONLY */