1
0
Fork 0
mirror of https://github.com/Ysurac/openmptcprouter.git synced 2025-02-15 04:42:02 +00:00
openmptcprouter/root/target/linux/brcm2708/patches-4.19/0556-dwc_otg-Choose-appropriate-IRQ-handover-strategy.patch
Ycarus (Yannick Chabanois) 5f08b288eb Add RPI4 beta support
2019-06-24 19:52:48 +02:00

196 lines
8 KiB
Diff

From 0a1cf0d4b15cd1e2d96f7c85cadc1b60c9337151 Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 21 May 2019 13:36:52 +0100
Subject: [PATCH 556/678] dwc_otg: Choose appropriate IRQ handover strategy
2711 has no MPHI peripheral, but the ARM Control block can fake
interrupts. Use the size of the DTB "mphi" reg block to determine
which is required.
Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
drivers/usb/host/dwc_otg/dwc_otg_driver.c | 9 +++--
drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 21 ++++++----
drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 2 +
drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 12 ++++--
drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 41 +++++++++++++-------
drivers/usb/host/dwc_otg/dwc_otg_os_dep.h | 3 ++
6 files changed, 60 insertions(+), 28 deletions(-)
diff --git a/drivers/usb/host/dwc_otg/dwc_otg_driver.c b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
index 3fd21c7ba360..6bfd35c57814 100644
--- a/drivers/usb/host/dwc_otg/dwc_otg_driver.c
+++ b/drivers/usb/host/dwc_otg/dwc_otg_driver.c
@@ -806,14 +806,15 @@ static int dwc_otg_driver_probe(
if (!request_mem_region(_dev->resource[1].start,
_dev->resource[1].end - _dev->resource[1].start + 1,
"dwc_otg")) {
- dev_dbg(&_dev->dev, "error reserving mapped memory\n");
- retval = -EFAULT;
- goto fail;
- }
+ dev_dbg(&_dev->dev, "error reserving mapped memory\n");
+ retval = -EFAULT;
+ goto fail;
+ }
dwc_otg_device->os_dep.mphi_base = ioremap_nocache(_dev->resource[1].start,
_dev->resource[1].end -
_dev->resource[1].start + 1);
+ dwc_otg_device->os_dep.use_swirq = (_dev->resource[1].end - _dev->resource[1].start) == 0x200;
}
#else
diff --git a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
index 3ac4c7984ce5..a86d8ed77140 100644
--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
@@ -1347,8 +1347,12 @@ void notrace dwc_otg_fiq_fsm(struct fiq_state *state, int num_channels)
/* We got an interrupt, didn't handle it. */
if (kick_irq) {
state->mphi_int_count++;
- FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
- FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
+ if (state->mphi_regs.swirq_set) {
+ FIQ_WRITE(state->mphi_regs.swirq_set, 1);
+ } else {
+ FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
+ FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
+ }
}
state->fiq_done++;
@@ -1406,11 +1410,14 @@ void notrace dwc_otg_fiq_nop(struct fiq_state *state)
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, state->dummy_send_dma);
- FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
-
+ if (state->mphi_regs.swirq_set) {
+ FIQ_WRITE(state->mphi_regs.swirq_set, 1);
+ } else {
+ /* Force a clear before another dummy send */
+ FIQ_WRITE(state->mphi_regs.intstat, (1<<29));
+ FIQ_WRITE(state->mphi_regs.outdda, state->dummy_send_dma);
+ FIQ_WRITE(state->mphi_regs.outddb, (1<<29));
+ }
}
state->fiq_done++;
mb();
diff --git a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
index f51737142188..537cc237b4bc 100644
--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
@@ -118,6 +118,8 @@ typedef struct {
volatile void* outdda;
volatile void* outddb;
volatile void* intstat;
+ volatile void* swirq_set;
+ volatile void* swirq_clr;
} mphi_regs_t;
enum fiq_debug_level {
diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
index 6947e98b87ad..d3097ef3728c 100644
--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
@@ -220,16 +220,20 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_hcd_t * dwc_otg_hcd)
/* The FIQ could have sneaked another interrupt in. If so, don't clear MPHI */
if ((gintmsk_new.d32 == ~0) && (haintmsk_new.d32 == 0x0000FFFF)) {
+ if (dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr) {
+ DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr, 1);
+ } else {
DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.intstat, (1<<16));
- if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) {
- fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR");
+ }
+ if (dwc_otg_hcd->fiq_state->mphi_int_count >= 50) {
+ fiq_print(FIQDBG_INT, dwc_otg_hcd->fiq_state, "MPHI CLR");
DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, ((1<<31) + (1<<16)));
while (!(DWC_READ_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & (1 << 17)))
;
DWC_WRITE_REG32(dwc_otg_hcd->fiq_state->mphi_regs.ctrl, (1<<31));
dwc_otg_hcd->fiq_state->mphi_int_count = 0;
- }
- int_done++;
+ }
+ int_done++;
}
haintmsk.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
/* Re-enable interrupts that the FIQ masked (first time round) */
diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
index fc43f2a66d6a..08a3e41038a3 100644
--- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
@@ -474,22 +474,37 @@ static void hcd_init_fiq(void *cookie)
set_fiq_regs(&regs);
#endif
- //Set the mphi periph to the required registers
- dwc_otg_hcd->fiq_state->mphi_regs.base = otg_dev->os_dep.mphi_base;
- dwc_otg_hcd->fiq_state->mphi_regs.ctrl = otg_dev->os_dep.mphi_base + 0x4c;
- dwc_otg_hcd->fiq_state->mphi_regs.outdda = otg_dev->os_dep.mphi_base + 0x28;
- dwc_otg_hcd->fiq_state->mphi_regs.outddb = otg_dev->os_dep.mphi_base + 0x2c;
- dwc_otg_hcd->fiq_state->mphi_regs.intstat = otg_dev->os_dep.mphi_base + 0x50;
dwc_otg_hcd->fiq_state->dwc_regs_base = otg_dev->os_dep.base;
- DWC_WARN("MPHI regs_base at %px", dwc_otg_hcd->fiq_state->mphi_regs.base);
- //Enable mphi peripheral
- writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
+ //Set the mphi periph to the required registers
+ dwc_otg_hcd->fiq_state->mphi_regs.base = otg_dev->os_dep.mphi_base;
+ if (otg_dev->os_dep.use_swirq) {
+ dwc_otg_hcd->fiq_state->mphi_regs.swirq_set =
+ otg_dev->os_dep.mphi_base + 0x1f0;
+ dwc_otg_hcd->fiq_state->mphi_regs.swirq_clr =
+ otg_dev->os_dep.mphi_base + 0x1f4;
+ DWC_WARN("Fake MPHI regs_base at 0x%08x",
+ (int)dwc_otg_hcd->fiq_state->mphi_regs.base);
+ } else {
+ dwc_otg_hcd->fiq_state->mphi_regs.ctrl =
+ otg_dev->os_dep.mphi_base + 0x4c;
+ dwc_otg_hcd->fiq_state->mphi_regs.outdda
+ = otg_dev->os_dep.mphi_base + 0x28;
+ dwc_otg_hcd->fiq_state->mphi_regs.outddb
+ = otg_dev->os_dep.mphi_base + 0x2c;
+ dwc_otg_hcd->fiq_state->mphi_regs.intstat
+ = otg_dev->os_dep.mphi_base + 0x50;
+ DWC_WARN("MPHI regs_base at %px",
+ dwc_otg_hcd->fiq_state->mphi_regs.base);
+
+ //Enable mphi peripheral
+ writel((1<<31),dwc_otg_hcd->fiq_state->mphi_regs.ctrl);
#ifdef DEBUG
- if (readl(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & 0x80000000)
- DWC_WARN("MPHI periph has been enabled");
- else
- DWC_WARN("MPHI periph has NOT been enabled");
+ if (readl(dwc_otg_hcd->fiq_state->mphi_regs.ctrl) & 0x80000000)
+ DWC_WARN("MPHI periph has been enabled");
+ else
+ DWC_WARN("MPHI periph has NOT been enabled");
#endif
+ }
// Enable FIQ interrupt from USB peripheral
#ifdef CONFIG_ARM64
irq = otg_dev->os_dep.fiq_num;
diff --git a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
index 3da96b253155..0e9a34fe3a5c 100644
--- a/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
+++ b/drivers/usb/host/dwc_otg/dwc_otg_os_dep.h
@@ -102,6 +102,9 @@ typedef struct os_dependent {
/** Base address for MPHI peripheral */
void *mphi_base;
+ /** mphi_base actually points to the SWIRQ block */
+ bool use_swirq;
+
/** IRQ number (<0 if not valid) */
int irq_num;
--
2.19.1