diff options
author | Shreshtha Kumar Sahu <shreshthakumar.sahu@stericsson.com> | 2011-11-17 17:28:12 +0530 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-05-22 11:02:33 +0200 |
commit | e2f33da595d1f9ff8c44b5b7a2de17953cea1484 (patch) | |
tree | 81fa6fedc02c201f0aaf137f7cbbcdbf42dbdb52 | |
parent | 76f377bd4a4189929b0322e018c21073c364fea2 (diff) |
u5500: pl011: Workaround for UART registers lockup
Deadlock situation which occurs during continuous
transfer of data for long duration over uart with
hardware flow control. It is observed that CTS
interrupt cannot be cleared in uart interrupt
register (ICR). Hence further transfer over
uart gets blocked.
amba-pl011 has mechanism to detect the situation,
handle the register configuration backup, hold the
uart transfer till workaround is excuting, restoring
the registers and resuming the trasfer afterwards.
This patch provides the platform reset function
to do a soft reset using PRCC_K_SOFTRST_SET/CLEAR
of UART-3 on which the issue is observed.
ST-Ericsson ID: 355971
ST-Ericsson Linux next: NA
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: If48863522c9ca3fced3cdce7689eff8d98cd1bbf
Signed-off-by: Shreshtha Kumar Sahu <shreshthakumar.sahu@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/38194
Reviewed-by: Srinidhi KASAGAR <srinidhi.kasagar@stericsson.com>
-rw-r--r-- | arch/arm/mach-ux500/board-u5500.c | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/arch/arm/mach-ux500/board-u5500.c b/arch/arm/mach-ux500/board-u5500.c index 0e200d1f6b8..6ec8e5e28fe 100644 --- a/arch/arm/mach-ux500/board-u5500.c +++ b/arch/arm/mach-ux500/board-u5500.c @@ -15,6 +15,7 @@ #ifdef CONFIG_STM_I2S #include <linux/i2s/i2s.h> #endif +#include <linux/delay.h> #include <linux/led-lm3530.h> #include <../drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h> #include <linux/input/matrix_keypad.h> @@ -648,6 +649,38 @@ static long u5500_panic_blink(int state) return 0; } +#define PRCC_K_SOFTRST_SET 0x18 +#define PRCC_K_SOFTRST_CLEAR 0x1C +/* pl011 reset */ +static void ux500_uart3_reset(void) +{ + void __iomem *prcc_rst_set, *prcc_rst_clr; + + prcc_rst_set = __io_address(U5500_CLKRST5_BASE + + PRCC_K_SOFTRST_SET); + prcc_rst_clr = __io_address(U5500_CLKRST5_BASE + + PRCC_K_SOFTRST_CLEAR); + + /* + * Activate soft reset PRCC_K_SOFTRST_CLEAR + * + * As we are dealing with IP register lockup + * so to make double sure that IP gets reset + * and reset pulse remains for more than one + * clock cycle a delay is added. + */ + writel((readl(prcc_rst_clr) | 0x08), prcc_rst_clr); + udelay(1); + + /* Release soft reset PRCC_K_SOFTRST_SET */ + writel((readl(prcc_rst_set) | 0x08), prcc_rst_set); + udelay(1); +} + +static struct amba_pl011_data uart3_plat = { + .reset = ux500_uart3_reset, +}; + static void __init u5500_i2c_init(struct device *parent) { db5500_add_i2c1(pareent, &u5500_i2c1_data); @@ -677,7 +710,7 @@ static void __init u5500_uart_init(struct device *parent) db5500_add_uart0(parent, NULL); db5500_add_uart1(parent, NULL); db5500_add_uart2(parent, NULL); - db5500_add_uart3(parent, NULL); + db5500_add_uart3(parent, &uart3_plat); } static void __init u5500_cryp1_hash1_init(void) |