Initial commit
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
From patchwork Fri Jul 13 11:32:42 2018
|
||||
Content-Type: text/plain; charset="utf-8"
|
||||
MIME-Version: 1.0
|
||||
Content-Transfer-Encoding: 7bit
|
||||
Subject: serial8250 on tegra hsuart: recover from spurious interrupts due to
|
||||
tegra2 silicon bug
|
||||
X-Patchwork-Submitter: "David R. Piegdon" <lkml@p23q.org>
|
||||
X-Patchwork-Id: 943440
|
||||
Message-Id: <4676ea34-69ce-5422-1ded-94218b89f7d9@p23q.org>
|
||||
To: linux-tegra@vger.kernel.org
|
||||
Date: Fri, 13 Jul 2018 11:32:42 +0000
|
||||
From: "David R. Piegdon" <lkml@p23q.org>
|
||||
List-Id: <linux-tegra.vger.kernel.org>
|
||||
|
||||
Hi,
|
||||
a while back I sent a few mails regarding spurious interrupts in the
|
||||
UARTA (hsuart) block of the Tegra2 SoC, when using the 8250 driver for
|
||||
it instead of the hsuart driver. After going down a pretty deep
|
||||
debugging/testing hole, I think I found a patch that fixes the issue. So
|
||||
far testing in a reboot-cycle suggests that the error frequency dropped
|
||||
from >3% of all reboots to at least <0.05% of all reboots. Tests
|
||||
continue to run over the weekend.
|
||||
|
||||
The patch below already is a second iteration; the first did not reset
|
||||
the MCR or contain the lines below '// clear interrupts'. This resulted
|
||||
in no more spurious interrupts, but in a few % of spurious interrupts
|
||||
that were recovered the UART block did not receive any characters any
|
||||
more. So further resetting was required to fully reacquire operational
|
||||
state of the UART block.
|
||||
|
||||
I'd love any comments/suggestions on this!
|
||||
|
||||
Cheers,
|
||||
|
||||
David
|
||||
|
||||
--- a/drivers/tty/serial/8250/8250_core.c
|
||||
+++ b/drivers/tty/serial/8250/8250_core.c
|
||||
@@ -133,6 +133,38 @@ static irqreturn_t serial8250_interrupt(
|
||||
|
||||
if (l == i->head && pass_counter++ > PASS_LIMIT)
|
||||
break;
|
||||
+
|
||||
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
||||
+ if (!handled && (port->type == PORT_TEGRA)) {
|
||||
+ /*
|
||||
+ * Fix Tegra 2 CPU silicon bug where sometimes
|
||||
+ * "TX holding register empty" interrupts result in a
|
||||
+ * bad (metastable?) state in Tegras HSUART IP core.
|
||||
+ * Only way to recover seems to be to reset all
|
||||
+ * interrupts as well as the TX queue and the MCR.
|
||||
+ * But we don't want to loose any outgoing characters,
|
||||
+ * so only do it if the RX and TX queues are empty.
|
||||
+ */
|
||||
+ unsigned char lsr = port->serial_in(port, UART_LSR);
|
||||
+ const unsigned char fifo_empty_mask =
|
||||
+ (UART_LSR_TEMT | UART_LSR_THRE);
|
||||
+ if (((lsr & (UART_LSR_DR | fifo_empty_mask)) ==
|
||||
+ fifo_empty_mask)) {
|
||||
+ port->serial_out(port, UART_IER, 0);
|
||||
+ port->serial_out(port, UART_MCR, 0);
|
||||
+ serial8250_clear_and_reinit_fifos(up);
|
||||
+ port->serial_out(port, UART_MCR, up->mcr);
|
||||
+ port->serial_out(port, UART_IER, up->ier);
|
||||
+ // clear interrupts
|
||||
+ serial_port_in(port, UART_LSR);
|
||||
+ serial_port_in(port, UART_RX);
|
||||
+ serial_port_in(port, UART_IIR);
|
||||
+ serial_port_in(port, UART_MSR);
|
||||
+ up->lsr_saved_flags = 0;
|
||||
+ up->msr_saved_flags = 0;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
} while (l != end);
|
||||
|
||||
spin_unlock(&i->lock);
|
||||
@@ -0,0 +1,46 @@
|
||||
--- a/arch/arm/boot/dts/tegra20-trimslice.dts
|
||||
+++ b/arch/arm/boot/dts/tegra20-trimslice.dts
|
||||
@@ -200,16 +200,17 @@
|
||||
conf_ata {
|
||||
nvidia,pins = "ata", "atc", "atd", "ate",
|
||||
"crtp", "dap2", "dap3", "dap4", "dta",
|
||||
- "dtb", "dtc", "dtd", "dte", "gmb",
|
||||
- "gme", "i2cp", "pta", "slxc", "slxd",
|
||||
- "spdi", "spdo", "uda";
|
||||
+ "dtb", "dtc", "dtd", "gmb", "gme",
|
||||
+ "i2cp", "pta", "slxc", "slxd", "spdi",
|
||||
+ "spdo", "uda";
|
||||
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
|
||||
nvidia,tristate = <TEGRA_PIN_ENABLE>;
|
||||
};
|
||||
conf_atb {
|
||||
nvidia,pins = "atb", "cdev1", "cdev2", "dap1",
|
||||
- "gma", "gmc", "gmd", "gpu", "gpu7",
|
||||
- "gpv", "sdio1", "slxa", "slxk", "uac";
|
||||
+ "dte", "gma", "gmc", "gmd", "gpu",
|
||||
+ "gpu7", "gpv", "sdio1", "slxa", "slxk",
|
||||
+ "uac";
|
||||
nvidia,pull = <TEGRA_PIN_PULL_NONE>;
|
||||
nvidia,tristate = <TEGRA_PIN_DISABLE>;
|
||||
};
|
||||
@@ -402,6 +403,20 @@
|
||||
};
|
||||
};
|
||||
|
||||
+ gpio-leds {
|
||||
+ compatible = "gpio-leds";
|
||||
+
|
||||
+ ds2 {
|
||||
+ label = "trimslice:green:right";
|
||||
+ gpios = <&gpio TEGRA_GPIO(D, 2) GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+
|
||||
+ ds3 {
|
||||
+ label = "trimslice:green:left";
|
||||
+ gpios = <&gpio TEGRA_GPIO(BB, 5) GPIO_ACTIVE_LOW>;
|
||||
+ };
|
||||
+ };
|
||||
+
|
||||
poweroff {
|
||||
compatible = "gpio-poweroff";
|
||||
gpios = <&gpio TEGRA_GPIO(X, 7) GPIO_ACTIVE_LOW>;
|
||||
Reference in New Issue
Block a user