提交 7ac90460 编写于 作者: X Xu Qiang 提交者: Zheng Zengkai

serial: amba-pl011: Fix serial port discard interrupt when interrupt signal...

serial: amba-pl011: Fix serial port discard interrupt when interrupt signal line of serial port is connected to mbigen.

ascend inclusion
category: bugfix
Bugzilla: https://gitee.com/openeuler/kernel/issues/I4K2U5
CVE: N/A

---------------------------------------

Hisi when designing ascend chip, connect the serial port interrupt
signal lines to mbigen equipment, mbigen write GICD_SETSPI_NSR
register trigger the SPI interrupt. This can result in serial
port drop interrupts.
Signed-off-by: NXu Qiang <xuqiang36@huawei.com>
Signed-off-by: NWang Wensheng <wangwensheng4@huawei.com>
Reviewed-by: NHanjun Guo <guohanjun@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 1012d464
...@@ -73,6 +73,24 @@ config SERIAL_AMBA_PL011_CONSOLE ...@@ -73,6 +73,24 @@ config SERIAL_AMBA_PL011_CONSOLE
your boot loader (lilo or loadlin) about how to pass options to the your boot loader (lilo or loadlin) about how to pass options to the
kernel at boot time.) kernel at boot time.)
if ASCEND_FEATURES
config SERIAL_ATTACHED_MBIGEN
bool "Serial port interrupt signal lines connected to the mbigen"
depends on SERIAL_AMBA_PL011=y
default n
help
Say Y here when the interrupt signal line of the serial port is
connected to the mbigne. The mbigen device has the function of
clearing interrupts automatically. However, the interrupt processing
function of the serial port driver may process multiple interrupts
at a time. The mbigen device cannot adapt to this scenario.
As a result, interrupts are lost.Because it maybe discard interrupt.
If unsure, say N.
endif
config SERIAL_EARLYCON_ARM_SEMIHOST config SERIAL_EARLYCON_ARM_SEMIHOST
bool "Early console using ARM semihosting" bool "Early console using ARM semihosting"
depends on ARM64 || ARM depends on ARM64 || ARM
......
...@@ -1466,6 +1466,65 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap) ...@@ -1466,6 +1466,65 @@ static void check_apply_cts_event_workaround(struct uart_amba_port *uap)
pl011_read(uap, REG_ICR); pl011_read(uap, REG_ICR);
} }
#ifdef CONFIG_SERIAL_ATTACHED_MBIGEN
struct workaround_oem_info {
char oem_id[ACPI_OEM_ID_SIZE + 1];
char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1];
u32 oem_revision;
};
static bool pl011_enable_hisi_wkrd;
static struct workaround_oem_info pl011_wkrd_info[] = {
{
.oem_id = "HISI ",
.oem_table_id = "HIP08 ",
.oem_revision = 0x300,
}, {
.oem_id = "HISI ",
.oem_table_id = "HIP08 ",
.oem_revision = 0x301,
}, {
.oem_id = "HISI ",
.oem_table_id = "HIP08 ",
.oem_revision = 0x400,
}, {
.oem_id = "HISI ",
.oem_table_id = "HIP08 ",
.oem_revision = 0x401,
}, {
.oem_id = "HISI ",
.oem_table_id = "HIP08 ",
.oem_revision = 0x402,
}
};
static void pl011_check_hisi_workaround(void)
{
struct acpi_table_header *tbl;
acpi_status status = AE_OK;
int i;
status = acpi_get_table(ACPI_SIG_MADT, 0, &tbl);
if (ACPI_FAILURE(status) || !tbl)
return;
for (i = 0; i < ARRAY_SIZE(pl011_wkrd_info); i++) {
if (!memcmp(pl011_wkrd_info[i].oem_id, tbl->oem_id, ACPI_OEM_ID_SIZE) &&
!memcmp(pl011_wkrd_info[i].oem_table_id, tbl->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) &&
pl011_wkrd_info[i].oem_revision == tbl->oem_revision) {
pl011_enable_hisi_wkrd = true;
break;
}
}
}
#else
#define pl011_enable_hisi_wkrd 0
static inline void pl011_check_hisi_workaround(void){ }
#endif
static irqreturn_t pl011_int(int irq, void *dev_id) static irqreturn_t pl011_int(int irq, void *dev_id)
{ {
struct uart_amba_port *uap = dev_id; struct uart_amba_port *uap = dev_id;
...@@ -1503,6 +1562,11 @@ static irqreturn_t pl011_int(int irq, void *dev_id) ...@@ -1503,6 +1562,11 @@ static irqreturn_t pl011_int(int irq, void *dev_id)
handled = 1; handled = 1;
} }
if (pl011_enable_hisi_wkrd) {
pl011_write(0, uap, REG_IMSC);
pl011_write(uap->im, uap, REG_IMSC);
}
spin_unlock_irqrestore(&uap->port.lock, flags); spin_unlock_irqrestore(&uap->port.lock, flags);
return IRQ_RETVAL(handled); return IRQ_RETVAL(handled);
...@@ -1680,6 +1744,8 @@ static int pl011_hwinit(struct uart_port *port) ...@@ -1680,6 +1744,8 @@ static int pl011_hwinit(struct uart_port *port)
if (plat->init) if (plat->init)
plat->init(); plat->init();
} }
pl011_check_hisi_workaround();
return 0; return 0;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册