From patchwork Wed Sep 7 12:53:30 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Govindraj.R" X-Patchwork-Id: 1127152 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.4) with ESMTP id p87G1Paa027119 for ; Wed, 7 Sep 2011 16:01:30 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755110Ab1IGQBG (ORCPT ); Wed, 7 Sep 2011 12:01:06 -0400 Received: from devils.ext.ti.com ([198.47.26.153]:48346 "EHLO devils.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754631Ab1IGQBA (ORCPT ); Wed, 7 Sep 2011 12:01:00 -0400 Received: from dbdp20.itg.ti.com ([172.24.170.38]) by devils.ext.ti.com (8.13.7/8.13.7) with ESMTP id p87Crq0A010055 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 7 Sep 2011 07:53:54 -0500 Received: from dbde70.ent.ti.com (localhost [127.0.0.1]) by dbdp20.itg.ti.com (8.13.8/8.13.8) with ESMTP id p87Crohs026936; Wed, 7 Sep 2011 18:23:51 +0530 (IST) Received: from dbdp31.itg.ti.com (172.24.170.98) by DBDE70.ent.ti.com (172.24.170.148) with Microsoft SMTP Server id 8.3.106.1; Wed, 7 Sep 2011 18:23:51 +0530 Received: from ula0131859.india.ti.com ([172.24.191.138]) by dbdp31.itg.ti.com (8.13.8/8.13.8) with ESMTP id p87Crjvv008977; Wed, 7 Sep 2011 18:23:50 +0530 (IST) From: "Govindraj.R" To: CC: , , "Govindraj.R" , Kevin Hilman , Paul Walmsley , Tony Lindgren , Vishwanath Sripathy , Partha Basak Subject: [PATCH v4 08/11] Serial: OMAP2+: Move erratum handling from serial.c Date: Wed, 7 Sep 2011 18:23:30 +0530 Message-ID: <1315400013-4849-9-git-send-email-govindraj.raja@ti.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1315400013-4849-1-git-send-email-govindraj.raja@ti.com> References: <1315400013-4849-1-git-send-email-govindraj.raja@ti.com> MIME-Version: 1.0 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Wed, 07 Sep 2011 16:01:30 +0000 (UTC) Move the erratum handling mechanism from serial.c to driver file and utilise the same func in driver file. Acked-by: Alan Cox Signed-off-by: Govindraj.R --- drivers/tty/serial/omap-serial.c | 58 ++++++++++++++++++++++++++++++++++--- 1 files changed, 53 insertions(+), 5 deletions(-) diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c index 30bdd05..96fc860 100644 --- a/drivers/tty/serial/omap-serial.c +++ b/drivers/tty/serial/omap-serial.c @@ -52,6 +52,7 @@ static struct uart_omap_port *ui[OMAP_MAX_HSUART_PORTS]; static void uart_tx_dma_callback(int lch, u16 ch_status, void *data); static void serial_omap_rx_timeout(unsigned long uart_no); static int serial_omap_start_rxdma(struct uart_omap_port *up); +static void omap_uart_mdr1_errataset(struct uart_omap_port *up, u8 mdr1); static inline unsigned int serial_in(struct uart_omap_port *up, int offset) { @@ -805,7 +806,11 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, /* Protocol, Baud Rate, and Interrupt Settings */ - serial_out(up, UART_OMAP_MDR1, up->mdr1); + if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) + omap_uart_mdr1_errataset(up, up->mdr1); + else + serial_out(up, UART_OMAP_MDR1, up->mdr1); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); up->efr = serial_in(up, UART_EFR); @@ -830,7 +835,10 @@ serial_omap_set_termios(struct uart_port *port, struct ktermios *termios, else up->mdr1 = UART_OMAP_MDR1_16X_MODE; - serial_out(up, UART_OMAP_MDR1, up->mdr1); + if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) + omap_uart_mdr1_errataset(up, up->mdr1); + else + serial_out(up, UART_OMAP_MDR1, up->mdr1); /* Hardware Flow Control Configuration */ @@ -1424,9 +1432,47 @@ static int serial_omap_remove(struct platform_device *dev) return 0; } +/* + * Work Around for Errata i202 (3430 - 1.12, 3630 - 1.6) + * The access to uart register after MDR1 Access + * causes UART to corrupt data. + * + * Need a delay = + * 5 L4 clock cycles + 5 UART functional clock cycle (@48MHz = ~0.2uS) + * give 10 times as much + */ +static void omap_uart_mdr1_errataset(struct uart_omap_port *up, u8 mdr1) +{ + u8 timeout = 255; + + serial_out(up, UART_OMAP_MDR1, mdr1); + udelay(2); + serial_out(up, UART_FCR, up->fcr | UART_FCR_CLEAR_XMIT | + UART_FCR_CLEAR_RCVR); + /* + * Wait for FIFO to empty: when empty, RX_FIFO_E bit is 0 and + * TX_FIFO_E bit is 1. + */ + while (UART_LSR_THRE != (serial_in(up, UART_LSR) & + (UART_LSR_THRE | UART_LSR_DR))) { + timeout--; + if (!timeout) { + /* Should *never* happen. we warn and carry on */ + dev_crit(&up->pdev->dev, "Errata i202: timedout %x\n", + serial_in(up, UART_LSR)); + break; + } + udelay(1); + } +} + static void omap_uart_restore_context(struct uart_omap_port *up) { - serial_out(up, UART_OMAP_MDR1, up->mdr1); + if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) + omap_uart_mdr1_errataset(up, UART_OMAP_MDR1_DISABLE); + else + serial_out(up, UART_OMAP_MDR1, UART_OMAP_MDR1_DISABLE); + serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */ serial_out(up, UART_EFR, UART_EFR_ECB); serial_out(up, UART_LCR, 0x0); /* Operational mode */ @@ -1442,8 +1488,10 @@ static void omap_uart_restore_context(struct uart_omap_port *up) serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B); /* Config B mode */ serial_out(up, UART_EFR, up->efr); serial_out(up, UART_LCR, up->lcr); - /* UART 16x mode */ - serial_out(up, UART_OMAP_MDR1, up->mdr1); + if (up->errata & UART_ERRATA_i202_MDR1_ACCESS) + omap_uart_mdr1_errataset(up, up->mdr1); + else + serial_out(up, UART_OMAP_MDR1, up->mdr1); } static int omap_serial_runtime_suspend(struct device *dev)