mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-06-19 12:12:16 +00:00
HV: vuart: support MSR and MCR
In Linux 8250 driver, it has different flags for UART ports. For COM1, COM2 and COM3, UPF_SKIP_TEST is set, which is used to skip the loopback test for the port. But for COM4, UPF_SKIP_TEST is not set, so when probing COM4, the driver will access MCR and MSR registers to make sure the port is exsit. So, add support for MSR and MCR. Default ports info: COM1, ttyS0, 0x3F8 COM2, ttyS1, 0x2F8 COM3, ttyS2, 0x3E8 COM4, ttyS3, 0x2E8 Tracked-On: #2987 Signed-off-by: Conghui Chen <conghui.chen@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
parent
4efc9e3ef9
commit
a090d03780
@ -120,6 +120,8 @@ static uint8_t vuart_intr_reason(const struct acrn_vuart *vu)
|
||||
ret = IIR_RXTOUT;
|
||||
} else if (vu->thre_int_pending && ((vu->ier & IER_ETBEI) != 0U)) {
|
||||
ret = IIR_TXRDY;
|
||||
} else if((vu->msr & MSR_DELTA_MASK) != 0 && (vu->ier & IER_EMSC) != 0) {
|
||||
ret = IIR_MLSC;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -182,6 +184,34 @@ static void vuart_write_to_target(struct acrn_vuart *vu, uint8_t value_u8)
|
||||
vuart_unlock(vu);
|
||||
}
|
||||
|
||||
static uint8_t modem_status(uint8_t mcr)
|
||||
{
|
||||
uint8_t msr;
|
||||
|
||||
if (mcr & MCR_LOOPBACK) {
|
||||
/*
|
||||
* In the loopback mode certain bits from the MCR are
|
||||
* reflected back into MSR.
|
||||
*/
|
||||
msr = 0;
|
||||
if (mcr & MCR_RTS)
|
||||
msr |= MSR_CTS;
|
||||
if (mcr & MCR_DTR)
|
||||
msr |= MSR_DSR;
|
||||
if (mcr & MCR_OUT1)
|
||||
msr |= MSR_RI;
|
||||
if (mcr & MCR_OUT2)
|
||||
msr |= MSR_DCD;
|
||||
} else {
|
||||
/*
|
||||
* Always assert DCD and DSR so tty open doesn't block
|
||||
* even if CLOCAL is turned off.
|
||||
*/
|
||||
msr = MSR_DCD | MSR_DSR;
|
||||
}
|
||||
return msr;
|
||||
}
|
||||
|
||||
static bool vuart_write(struct acrn_vm *vm, uint16_t offset_arg,
|
||||
__unused size_t width, uint32_t value)
|
||||
{
|
||||
@ -189,11 +219,14 @@ static bool vuart_write(struct acrn_vm *vm, uint16_t offset_arg,
|
||||
struct acrn_vuart *vu = find_vuart_by_port(vm, offset);
|
||||
uint8_t value_u8 = (uint8_t)value;
|
||||
struct acrn_vuart *target_vu = NULL;
|
||||
uint8_t msr;
|
||||
|
||||
if (vu) {
|
||||
offset -= vu->port_base;
|
||||
target_vu = vu->target_vu;
|
||||
if ((offset == UART16550_THR) && target_vu) {
|
||||
|
||||
if (!(vu->mcr & MCR_LOOPBACK) &&
|
||||
(offset == UART16550_THR) && target_vu) {
|
||||
vuart_write_to_target(target_vu, value_u8);
|
||||
} else {
|
||||
vuart_lock(vu);
|
||||
@ -207,7 +240,12 @@ static bool vuart_write(struct acrn_vm *vm, uint16_t offset_arg,
|
||||
} else {
|
||||
switch (offset) {
|
||||
case UART16550_THR:
|
||||
fifo_putchar(&vu->txfifo, (char)value_u8);
|
||||
if (vu->mcr & MCR_LOOPBACK) {
|
||||
fifo_putchar(&vu->rxfifo, (char)value_u8);
|
||||
vu->lsr |= LSR_OE;
|
||||
} else {
|
||||
fifo_putchar(&vu->txfifo, (char)value_u8);
|
||||
}
|
||||
vu->thre_int_pending = true;
|
||||
break;
|
||||
case UART16550_IER:
|
||||
@ -236,7 +274,28 @@ static bool vuart_write(struct acrn_vm *vm, uint16_t offset_arg,
|
||||
vu->lcr = value_u8;
|
||||
break;
|
||||
case UART16550_MCR:
|
||||
/* ignore modem */
|
||||
/* Apply mask so that bits 5-7 are 0 */
|
||||
vu->mcr = value & 0x1F;
|
||||
msr = modem_status(vu->mcr);
|
||||
/*
|
||||
* Detect if there has been any change between the
|
||||
* previous and the new value of MSR. If there is
|
||||
* then assert the appropriate MSR delta bit.
|
||||
*/
|
||||
if ((msr & MSR_CTS) ^ (vu->msr & MSR_CTS))
|
||||
vu->msr |= MSR_DCTS;
|
||||
if ((msr & MSR_DSR) ^ (vu->msr & MSR_DSR))
|
||||
vu->msr |= MSR_DDSR;
|
||||
if ((msr & MSR_DCD) ^ (vu->msr & MSR_DCD))
|
||||
vu->msr |= MSR_DDCD;
|
||||
if ((vu->msr & MSR_RI) != 0 && (msr & MSR_RI) == 0)
|
||||
vu->msr |= MSR_TERI;
|
||||
/*
|
||||
* Update the value of MSR while retaining the delta
|
||||
* bits.
|
||||
*/
|
||||
vu->msr &= MSR_DELTA_MASK;
|
||||
vu->msr |= msr;
|
||||
break;
|
||||
case UART16550_LSR:
|
||||
/*
|
||||
@ -332,8 +391,11 @@ static bool vuart_read(struct acrn_vm *vm, struct acrn_vcpu *vcpu, uint16_t offs
|
||||
vu->lsr &= ~LSR_OE;
|
||||
break;
|
||||
case UART16550_MSR:
|
||||
/* ignore modem I*/
|
||||
reg = 0U;
|
||||
/*
|
||||
* MSR delta bits are cleared on read
|
||||
*/
|
||||
reg = vu->msr;
|
||||
vu->msr &= ~MSR_DELTA_MASK;
|
||||
break;
|
||||
case UART16550_SCR:
|
||||
reg = vu->scr;
|
||||
|
@ -36,6 +36,7 @@
|
||||
/* value definitions for IIR */
|
||||
#define IIR_FIFO_MASK 0xc0U /* set if FIFOs are enabled */
|
||||
#define IIR_RXTOUT 0x0cU
|
||||
#define IER_EMSC 0x08U
|
||||
#define IIR_RLS 0x06U
|
||||
#define IIR_RXRDY 0x04U
|
||||
#define IIR_TXRDY 0x02U
|
||||
@ -87,9 +88,29 @@
|
||||
#define LSR_DR (1U << 0U)
|
||||
|
||||
/* definition for MCR */
|
||||
#define MCR_PRESCALE (1U << 7U) /* only available on 16650 up */
|
||||
#define MCR_LOOPBACK (1U << 4U)
|
||||
#define MCR_IE (1U << 3U)
|
||||
#define MCR_IENABLE MCR_IE
|
||||
#define MCR_DRS (1U << 2U)
|
||||
#define MCR_RTS (1U << 1U) /* Request to Send */
|
||||
#define MCR_DTR (1U << 0U) /* Data Terminal Ready */
|
||||
|
||||
/* defifor MSR */
|
||||
#define MSR_DCD (1U << 7U)
|
||||
#define MSR_RI (1U << 6U)
|
||||
#define MSR_DSR (1U << 5U)
|
||||
#define MSR_CTS (1U << 4U)
|
||||
#define MSR_DDCD (1U << 3U)
|
||||
#define MSR_TERI (1U << 2U)
|
||||
#define MSR_DDSR (1U << 1U)
|
||||
#define MSR_DCTS (1U << 0U)
|
||||
|
||||
#define MCR_OUT2 (1U << 3U)
|
||||
#define MCR_OUT1 (1U << 2U)
|
||||
|
||||
#define MSR_DELTA_MASK 0x0FU
|
||||
|
||||
/* definition for FCR */
|
||||
#define FCR_RX_MASK 0xc0U
|
||||
#define FCR_DMA (1U << 3U)
|
||||
|
Loading…
Reference in New Issue
Block a user