All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>
To: WX Chen <wxchen0913@gmail.com>, qemu-devel@nongnu.org
Cc: "Paolo Bonzini" <pbonzini@redhat.com>,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>,
	"Chao Liu" <chao.liu.zevorn@gmail.com>,
	"Palmer Dabbelt" <palmer@dabbelt.com>,
	"Alistair Francis" <alistair.francis@wdc.com>,
	"Weiwei Li" <liwei1518@gmail.com>,
	"Liu Zhiwei" <zhiwei_liu@linux.alibaba.com>,
	qemu-riscv@nongnu.org, "Fabiano Rosas" <farosas@suse.de>,
	"Laurent Vivier" <lvivier@redhat.com>
Subject: Re: [PATCH RESEND v2 3/3] tests/qtest: add K230 UART test
Date: Wed, 5 Aug 2026 17:10:17 -0300	[thread overview]
Message-ID: <af3d837c-e7f2-48ce-9b9c-c2ea9e4d8fb8@oss.qualcomm.com> (raw)
In-Reply-To: <20260725-feat-k230-uart-v2-v2-3-d5fe82c47c28@gmail.com>



On 7/25/2026 12:52 AM, WX Chen wrote:
> Add 8 test cases covering the main register paths and driver usage
> scenarios: device probe, init & baud, TX/RX datapath, THRE interrupt,
> RX interrupts (timeout & trigger level), error interrupts & IIR
> priority, USR & busy detect, and advanced features (shadow registers,
> HTX, SRR, PTIME/TET).
> 
> All tests pass.
> 
> Signed-off-by: WX Chen <wxchen0913@gmail.com>
> ---

This also LGTM with a minor observation down there:



>   tests/qtest/k230-uart-test.c | 514 +++++++++++++++++++++++++++++++++++++++++++
>   tests/qtest/meson.build      |   2 +-
>   2 files changed, 515 insertions(+), 1 deletion(-)
> 
> diff --git a/tests/qtest/k230-uart-test.c b/tests/qtest/k230-uart-test.c
> new file mode 100644
> index 0000000000000000000000000000000000000000..f85c690ebb57abb5b7f753f36c06c0900c3cfbb9
> --- /dev/null
> +++ b/tests/qtest/k230-uart-test.c
> @@ -0,0 +1,514 @@
> +/*
> + * QTest for the K230 UART — functional-path coverage.
> + *
> + * Tests are organised around driver usage scenarios rather than
> + * enumerating every register in isolation.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "libqtest.h"
> +#include <string.h>
> +
> +#define UART_BASE  0x91400000
> +#define R(off)     (UART_BASE + (off))
> +
> +/* register offsets */
> +#define THR    0x00
> +#define IER    0x04
> +#define IIR    0x08
> +#define LCR    0x0c
> +#define MCR    0x10
> +#define LSR    0x14
> +#define SCR    0x1c
> +#define USR    0x7c
> +#define TFL    0x80
> +#define RFL    0x84
> +#define SRR    0x88
> +#define SRTS   0x8c
> +#define SBCR   0x90
> +#define SDMAM  0x94
> +#define SFE    0x98
> +#define SRT    0x9c
> +#define STET   0xa0
> +#define HTX    0xa4
> +#define CPR    0xf4
> +#define CTR    0xfc
> +
> +/* bit fields */
> +#define LCR_DLAB     0x80
> +#define LCR_BC       0x40
> +#define LCR_8N1      0x03
> +
> +#define LSR_DR       0x01
> +#define LSR_OE       0x02
> +#define LSR_THRE     0x20
> +#define LSR_TEMT     0x40
> +#define LSR_RESET    0x60
> +
> +#define IIR_IID      0x0f
> +#define IIR_NONE     0x01
> +#define IIR_THR      0x02
> +#define IIR_RX       0x04
> +#define IIR_LINE     0x06
> +#define IIR_BUSY     0x07
> +#define IIR_TO       0x0c
> +#define IIR_FF       0xc0
> +
> +#define IER_RX       0x01
> +#define IER_TX       0x02
> +#define IER_LS       0x04
> +#define IER_COLR     0x10
> +#define IER_PTIME    0x80
> +
> +#define MCR_LB       0x10
> +#define MCR_RTS      0x02
> +
> +#define FCR_FE       0x01
> +#define FCR_RR       0x02
> +#define FCR_XR       0x04
> +#define FCR_TET_H    (3 << 4)
> +#define FCR_RT_Q     (1 << 6)
> +#define FCR_RT_F     (3 << 6)
> +
> +#define USR_BUSY     0x01
> +#define USR_RESET    0x06
> +
> +#define SRR_UR       0x01
> +#define SRR_RFR      0x02
> +
> +/* helpers */
> +static uint32_t rd(QTestState *qts, uint32_t o)
> +{
> +    return qtest_readl(qts, R(o));
> +}
> +static uint32_t iid(QTestState *qts)
> +{
> +    return rd(qts, IIR) & IIR_IID;
> +}
> +
> +static void poll_lsr(QTestState *qts, uint32_t m)
> +{
> +    int i;
> +
> +    for (i = 0; i < 1000; i++) {
> +        if (rd(qts, LSR) & m) {
> +            return;
> +        }
> +        g_usleep(1000);

Any reason to use g_usleep() instead of qtest_clock_step()?  There are a couple
of g_usleep() uses in the code but you used lots of qtest_clock_step() too.

AFAIK g_usleep() is wall time and qtest_clock_step() is simulated time, and
I guess you should be using qtest_clock_step() for all the pollings you're
doing in this file.


Thanks,
Daniel


> +    }
> +    g_assert_not_reached();
> +}
> +
> +static void s1(QTestState *qts, int fd, char c)
> +{
> +    g_assert_cmpint(send(fd, &c, 1, 0), ==, 1);
> +    poll_lsr(qts, LSR_DR);
> +}
> +
> +static void sn(QTestState *qts, int fd, const char *d, int n)
> +{
> +    g_assert_cmpint(send(fd, d, n, 0), ==, n);
> +    poll_lsr(qts, LSR_DR);
> +}
> +
> +static void oe_nf(QTestState *qts, int fd)
> +{
> +    int i;
> +
> +    s1(qts, fd, 'A');
> +    {
> +        char c = 'B';
> +        g_assert_cmpint(send(fd, &c, 1, 0), ==, 1);
> +    }
> +    for (i = 0; i < 200; i++) {
> +        rd(qts, SCR);
> +        g_usleep(1000);
> +    }
> +}
> +
> +/* 1. device probe */
> +static void test_device_probe(void)
> +{
> +    QTestState *qts = qtest_init("-machine k230");
> +    uint32_t cpr = rd(qts, CPR);
> +
> +    g_assert_cmphex(cpr & 0x3, ==, 0x2);
> +    g_assert_cmphex(cpr & (1 << 5), ==, (1 << 5));
> +    g_assert_cmphex(cpr & (1 << 8), ==, (1 << 8));
> +    g_assert_cmphex((cpr >> 16) & 0xff, ==, 0x2);
> +    g_assert_cmphex(cpr & (1 << 4), ==, 0);
> +    g_assert_cmphex(rd(qts, CTR), ==, 0x44570110);
> +    g_assert_cmphex(rd(qts, LSR), ==, LSR_RESET);
> +    g_assert_cmphex(rd(qts, USR), ==, USR_RESET);
> +    g_assert_cmphex(iid(qts), ==, IIR_NONE);
> +    g_assert_cmphex(rd(qts, IIR) & IIR_FF, ==, 0);
> +    g_assert_cmphex(rd(qts, USR) & USR_BUSY, ==, 0);
> +
> +    qtest_writel(qts, R(IIR), FCR_FE);
> +    g_assert_cmphex(rd(qts, IIR) & IIR_FF, ==, IIR_FF);
> +    qtest_quit(qts);
> +}
> +
> +/* 2. init & baud */
> +static void test_init_and_baud(void)
> +{
> +    int fd;
> +    QTestState *qts = qtest_init_with_serial("-machine k230", &fd);
> +
> +    qtest_writel(qts, R(LCR), LCR_DLAB);
> +    qtest_writel(qts, R(THR), 0x55);
> +    g_assert_cmphex(rd(qts, THR), ==, 0x55);
> +    qtest_writel(qts, R(LCR), LCR_8N1);
> +    g_assert_cmphex(rd(qts, THR), ==, 0x00);
> +
> +    qtest_writel(qts, R(IIR), FCR_FE | FCR_RT_F);
> +    qtest_writel(qts, R(IER), IER_RX);
> +
> +    /* divisor=1 -> timeout=12800ns */
> +    qtest_writel(qts, R(LCR), LCR_8N1 | LCR_DLAB);
> +    qtest_writel(qts, R(THR), 1); qtest_writel(qts, R(IER), 0);
> +    qtest_writel(qts, R(LCR), LCR_8N1);
> +    s1(qts, fd, 'X');
> +    qtest_clock_step(qts, 13000);
> +    g_assert_cmphex(iid(qts), ==, IIR_TO);
> +
> +    /* divisor=100 -> timeout=1.28e6ns; 13000ns too short */
> +    rd(qts, THR);
> +    qtest_writel(qts, R(LCR), LCR_8N1 | LCR_DLAB);
> +    qtest_writel(qts, R(THR), 100); qtest_writel(qts, R(IER), 0);
> +    qtest_writel(qts, R(LCR), LCR_8N1);
> +    s1(qts, fd, 'Y');
> +    qtest_clock_step(qts, 13000);
> +    g_assert_cmphex(iid(qts), !=, IIR_TO);
> +    qtest_clock_step(qts, 1300000);
> +    g_assert_cmphex(iid(qts), ==, IIR_TO);
> +
> +    close(fd); qtest_quit(qts);
> +}
> +
> +/* 3. TX / RX datapath */
> +static void test_tx_rx_datapath(void)
> +{
> +    int fd;
> +    QTestState *qts = qtest_init_with_serial("-machine k230", &fd);
> +
> +    qtest_writel(qts, R(LCR), LCR_8N1);
> +    g_assert_cmphex(rd(qts, LSR) & (LSR_THRE | LSR_TEMT),
> +                    ==, LSR_THRE | LSR_TEMT);
> +    qtest_writel(qts, R(THR), 'A');
> +    g_assert_cmphex(rd(qts, LSR) & (LSR_THRE | LSR_TEMT),
> +                    ==, LSR_THRE | LSR_TEMT);
> +
> +    /* external RX (FIFO mode) */
> +    qtest_writel(qts, R(IIR), FCR_FE);
> +    qtest_writel(qts, R(IER), IER_RX);
> +    sn(qts, fd, "K230", 4);
> +    for (int i = 0; i < 4; i++) {
> +        if (i < 3) {
> +            g_assert_cmphex(iid(qts), ==, IIR_RX);
> +        }
> +        g_assert_cmphex(rd(qts, THR), ==, "K230"[i]);
> +    }
> +    g_assert_cmphex(rd(qts, LSR) & LSR_DR, ==, 0);
> +
> +    /* loopback */
> +    qtest_writel(qts, R(MCR), MCR_LB);
> +    qtest_writel(qts, R(THR), 'L');
> +    g_assert_cmphex(rd(qts, THR), ==, 'L');
> +    g_assert_cmphex(rd(qts, LSR) & LSR_DR, ==, 0);
> +
> +    /* no loopback */
> +    qtest_writel(qts, R(MCR), 0);
> +    qtest_writel(qts, R(THR), 'Z');
> +    g_assert_cmphex(rd(qts, LSR) & LSR_DR, ==, 0);
> +
> +    /* TFL / RFL */
> +    qtest_writel(qts, R(MCR), MCR_LB);
> +    qtest_writel(qts, R(IIR), FCR_FE | FCR_RR | FCR_XR);
> +    qtest_writel(qts, R(THR), 'X'); qtest_writel(qts, R(THR), 'Y');
> +    g_assert_cmphex(rd(qts, TFL), ==, 0);
> +    g_assert_cmphex(rd(qts, RFL), ==, 2);
> +
> +    /* non-FIFO mode */
> +    qtest_writel(qts, R(MCR), 0);
> +    qtest_writel(qts, R(IIR), 0);
> +    s1(qts, fd, 'N');
> +    g_assert_cmphex(rd(qts, THR), ==, 'N');
> +    g_assert_cmphex(rd(qts, LSR) & LSR_DR, ==, 0);
> +
> +    /* non-FIFO overrun */
> +    int i;
> +    s1(qts, fd, 'n');
> +    g_assert_cmphex(rd(qts, LSR) & LSR_DR, ==, LSR_DR);
> +    {
> +        char c = 'o';
> +        send(fd, &c, 1, 0);
> +    }
> +    for (i = 0; i < 200; i++) {
> +        rd(qts, SCR);
> +        g_usleep(1000);
> +    }
> +    g_assert_cmphex(rd(qts, LSR) & LSR_OE, ==, LSR_OE);
> +
> +    close(fd); qtest_quit(qts);
> +}
> +
> +/* 4. THRE interrupt */
> +static void test_thre_interrupt(void)
> +{
> +    QTestState *qts = qtest_init("-machine k230 "
> +                                 "-chardev null,id=c0 -serial chardev:c0");
> +    qtest_writel(qts, R(LCR), LCR_8N1);
> +
> +    qtest_writel(qts, R(THR), 'A');
> +    g_assert_cmphex(iid(qts), ==, IIR_NONE);
> +
> +    qtest_writel(qts, R(IER), IER_TX);
> +    g_assert_cmphex(iid(qts), ==, IIR_THR);
> +
> +    qtest_writel(qts, R(THR), 'B');
> +    g_assert_cmphex(iid(qts), ==, IIR_THR);
> +
> +    g_assert_cmphex(iid(qts), ==, IIR_NONE);
> +    qtest_quit(qts);
> +}
> +
> +/* 5. RX interrupts: timeout & trigger level */
> +static void test_rx_interrupts(void)
> +{
> +    int fd;
> +    QTestState *qts = qtest_init_with_serial("-machine k230", &fd);
> +
> +    qtest_writel(qts, R(LCR), LCR_8N1);
> +    qtest_writel(qts, R(IIR), FCR_FE | FCR_RT_F);
> +    qtest_writel(qts, R(IER), IER_RX);
> +
> +    /* basic timeout */
> +    s1(qts, fd, 'T');
> +    qtest_clock_step(qts, 400000);
> +    g_assert_cmphex(iid(qts), ==, IIR_TO);
> +    g_assert_cmphex(rd(qts, THR), ==, 'T');
> +    g_assert_cmphex(iid(qts), !=, IIR_TO);
> +
> +    /* timeout reset by new byte */
> +    s1(qts, fd, 'A'); qtest_clock_step(qts, 200000);
> +    s1(qts, fd, 'B');
> +    qtest_clock_step(qts, 200000);
> +    g_assert_cmphex(iid(qts), ==, IIR_NONE);
> +    qtest_clock_step(qts, 200000);
> +    g_assert_cmphex(iid(qts), ==, IIR_TO);
> +    rd(qts, THR);
> +    rd(qts, THR);
> +
> +    /* timeout rearmed by partial drain */
> +    s1(qts, fd, 'X');
> +    s1(qts, fd, 'Y');
> +    qtest_clock_step(qts, 400000);
> +    g_assert_cmphex(iid(qts), ==, IIR_TO);
> +    g_assert_cmphex(rd(qts, THR), ==, 'X');
> +    qtest_clock_step(qts, 200000);
> +    g_assert_cmphex(iid(qts), !=, IIR_TO);
> +    qtest_clock_step(qts, 250000);
> +    g_assert_cmphex(iid(qts), ==, IIR_TO);
> +    g_assert_cmphex(rd(qts, THR), ==, 'Y');
> +
> +    /* RX trigger level: RT=Q -> trigger at 8 bytes */
> +    qtest_writel(qts, R(IIR), FCR_FE | FCR_RT_Q);
> +    sn(qts, fd, "ABCDEFG", 7);
> +    g_usleep(20000);
> +    g_assert_cmphex(iid(qts), ==, IIR_NONE);
> +    qtest_clock_step(qts, 400000);
> +    g_assert_cmphex(iid(qts), ==, IIR_TO);
> +    for (int i = 0; i < 7; i++) {
> +        rd(qts, THR);
> +    }
> +
> +    sn(qts, fd, "12345678", 8);
> +    for (int i = 0; i < 1000; i++) {
> +        if (iid(qts) == IIR_RX) {
> +            break;
> +        }
> +        g_usleep(1000);
> +    }
> +    g_assert_cmphex(iid(qts), ==, IIR_RX);
> +
> +    close(fd); qtest_quit(qts);
> +}
> +
> +/* 6. error interrupts & IIR priority */
> +static void test_error_interrupts(void)
> +{
> +    int fd;
> +    QTestState *qts = qtest_init_with_serial("-machine k230", &fd);
> +
> +    qtest_writel(qts, R(LCR), LCR_8N1);
> +    qtest_writel(qts, R(IER), IER_LS);
> +
> +    /* OE -> IIR=0x6; LSR clears; ELCOLR=0: RBR clears; ELCOLR=1: RBR keeps */
> +    oe_nf(qts, fd);
> +    g_assert_cmphex(iid(qts), ==, IIR_LINE);
> +    rd(qts, LSR);
> +    g_assert_cmphex(iid(qts), !=, IIR_LINE);
> +
> +    oe_nf(qts, fd);
> +    g_assert_cmphex(iid(qts), ==, IIR_LINE);
> +    rd(qts, THR);
> +    g_assert_cmphex(iid(qts), !=, IIR_LINE);
> +
> +    qtest_writel(qts, R(IER), IER_LS | IER_COLR);
> +    oe_nf(qts, fd);
> +    g_assert_cmphex(iid(qts), ==, IIR_LINE);
> +    rd(qts, THR);
> +    g_assert_cmphex(iid(qts), ==, IIR_LINE);
> +    rd(qts, LSR);
> +    g_assert_cmphex(iid(qts), !=, IIR_LINE);
> +
> +    /* IIR priority: RX > TX (loopback) */
> +    qtest_writel(qts, R(IIR), FCR_FE);
> +    qtest_writel(qts, R(MCR), MCR_LB);
> +    qtest_writel(qts, R(IER), IER_TX | IER_RX);
> +    qtest_writel(qts, R(THR), 'P');
> +    g_assert_cmphex(iid(qts), ==, IIR_RX);
> +    g_assert_cmphex(rd(qts, THR), ==, 'P');
> +    g_assert_cmphex(iid(qts), ==, IIR_THR);
> +    iid(qts);
> +    g_assert_cmphex(iid(qts), ==, IIR_NONE);
> +
> +    /* OE in FIFO mode via loopback */
> +    qtest_writel(qts, R(IER), IER_LS);
> +    for (int i = 0; i < 32; i++) {
> +        qtest_writel(qts, R(THR), 'a');
> +    }
> +    g_assert_cmphex(rd(qts, LSR) & LSR_OE, ==, 0);
> +    qtest_writel(qts, R(THR), 'z');
> +    g_assert_cmphex(iid(qts), ==, IIR_LINE);
> +    g_assert_cmphex(rd(qts, LSR) & LSR_OE, ==, LSR_OE);
> +
> +    close(fd); qtest_quit(qts);
> +}
> +
> +/* 7. USR & busy detect */
> +static void test_busy_detect(void)
> +{
> +    int fd;
> +    QTestState *qts = qtest_init_with_serial("-machine k230", &fd);
> +
> +    qtest_writel(qts, R(LCR), LCR_8N1);
> +    qtest_writel(qts, R(IIR), FCR_FE);
> +
> +    g_assert_cmphex(rd(qts, USR) & 0x1e, ==, 0x06);
> +
> +    qtest_writel(qts, R(MCR), MCR_LB);
> +    qtest_writel(qts, R(THR), 'A');
> +    g_assert_cmphex(rd(qts, USR) & 0x08, ==, 0x08);
> +    rd(qts, THR);
> +    g_assert_cmphex(rd(qts, USR) & 0x08, ==, 0);
> +    qtest_writel(qts, R(MCR), 0);
> +
> +    /* BUSY via RX & loopback */
> +    g_assert_cmphex(rd(qts, USR) & USR_BUSY, ==, 0);
> +    s1(qts, fd, 'Z');
> +    g_assert_cmphex(rd(qts, USR) & USR_BUSY, ==, USR_BUSY);
> +    rd(qts, THR);
> +    g_assert_cmphex(rd(qts, USR) & USR_BUSY, ==, 0);
> +
> +    qtest_writel(qts, R(MCR), MCR_LB);
> +    qtest_writel(qts, R(THR), 'L');
> +    g_assert_cmphex(rd(qts, USR) & USR_BUSY, ==, USR_BUSY);
> +    rd(qts, THR);
> +    g_assert_cmphex(rd(qts, USR) & USR_BUSY, ==, 0);
> +
> +    /* busy-detect: LCR write rejected while BUSY=1 */
> +    qtest_writel(qts, R(MCR), 0);
> +    qtest_writel(qts, R(IIR), FCR_FE | FCR_RR | FCR_XR);
> +    s1(qts, fd, 'B');
> +    g_assert_cmphex(rd(qts, USR) & USR_BUSY, ==, USR_BUSY);
> +    qtest_writel(qts, R(LCR), LCR_8N1 | LCR_DLAB);
> +    g_assert_cmphex(rd(qts, LCR), ==, LCR_8N1);
> +    g_assert_cmphex(iid(qts), ==, IIR_BUSY);
> +    rd(qts, USR);
> +    g_assert_cmphex(iid(qts), ==, IIR_NONE);
> +    qtest_writel(qts, R(IIR), FCR_FE | FCR_RR);
> +    g_assert_cmphex(rd(qts, USR) & USR_BUSY, ==, 0);
> +    qtest_writel(qts, R(LCR), LCR_8N1 | LCR_DLAB);
> +    g_assert_cmphex(rd(qts, LCR), ==, LCR_8N1 | LCR_DLAB);
> +
> +    close(fd); qtest_quit(qts);
> +}
> +
> +/* 8. advanced features */
> +static void test_advanced_features(void)
> +{
> +    QTestState *qts = qtest_init("-machine k230 "
> +                                 "-chardev null,id=c0 -serial chardev:c0");
> +
> +    /* shadow: SRTS<->MCR.RTS, SBCR<->LCR.BC, SDMAM, SFE, SRT, STET, HTX */
> +    qtest_writel(qts, R(SRTS), 1);
> +    g_assert_cmphex(rd(qts, MCR) & MCR_RTS, ==, MCR_RTS);
> +    qtest_writel(qts, R(MCR), 0); g_assert_cmphex(rd(qts, SRTS), ==, 0);
> +    qtest_writel(qts, R(SBCR), 1);
> +    g_assert_cmphex(rd(qts, LCR) & LCR_BC, ==, LCR_BC);
> +    qtest_writel(qts, R(LCR), 0); g_assert_cmphex(rd(qts, SBCR), ==, 0);
> +    qtest_writel(qts, R(SDMAM), 1); g_assert_cmphex(rd(qts, SDMAM), ==, 1);
> +    qtest_writel(qts, R(SRT), 0x2); g_assert_cmphex(rd(qts, SRT), ==, 0x2);
> +    qtest_writel(qts, R(STET), 0x3); g_assert_cmphex(rd(qts, STET), ==, 0x3);
> +    qtest_writel(qts, R(SFE), 1); g_assert_cmphex(rd(qts, SFE), ==, 1);
> +    g_assert_cmphex(rd(qts, IIR) & IIR_FF, ==, IIR_FF);
> +    qtest_writel(qts, R(HTX), 1); g_assert_cmphex(rd(qts, HTX), ==, 1);
> +    qtest_writel(qts, R(HTX), 0); g_assert_cmphex(rd(qts, HTX), ==, 0);
> +
> +    /* HTX halt TX */
> +    qtest_writel(qts, R(LCR), LCR_8N1);
> +    qtest_writel(qts, R(IIR), FCR_FE);
> +    qtest_writel(qts, R(MCR), MCR_LB);
> +
> +    qtest_writel(qts, R(HTX), 1);
> +    qtest_writel(qts, R(THR), 'H');
> +    g_assert_cmphex(rd(qts, TFL), ==, 1);
> +    g_assert_cmphex(rd(qts, RFL), ==, 0);
> +
> +    qtest_writel(qts, R(HTX), 0);
> +    g_assert_cmphex(rd(qts, TFL), ==, 0);
> +    g_assert_cmphex(rd(qts, RFL), ==, 1);
> +    g_assert_cmphex(rd(qts, THR), ==, 'H');
> +
> +    /* SRR: RFR & UR */
> +    qtest_writel(qts, R(THR), 'Z');
> +    g_assert_cmphex(rd(qts, RFL), ==, 1);
> +    g_assert_cmphex(rd(qts, LSR) & LSR_DR, ==, LSR_DR);
> +    qtest_writel(qts, R(SRR), SRR_RFR);
> +    g_assert_cmphex(rd(qts, RFL), ==, 0);
> +    g_assert_cmphex(rd(qts, LSR) & LSR_DR, ==, 0);
> +    g_assert_cmphex(rd(qts, SRR), ==, 0);
> +    qtest_writel(qts, R(THR), 'Y');
> +    qtest_writel(qts, R(SRR), SRR_UR);
> +    g_assert_cmphex(rd(qts, LSR), ==, LSR_RESET);
> +    g_assert_cmphex(iid(qts), ==, IIR_NONE);
> +    g_assert_cmphex(rd(qts, RFL), ==, 0);
> +
> +    /* PTIME + TET programmable THRE */
> +    qtest_writel(qts, R(LCR), LCR_8N1);
> +    qtest_writel(qts, R(IIR), FCR_FE | FCR_TET_H);
> +    qtest_writel(qts, R(IER), IER_TX | IER_PTIME);
> +    qtest_writel(qts, R(THR), 'A');
> +    g_assert_cmphex(rd(qts, LSR) & LSR_THRE, ==, LSR_THRE);
> +    g_assert_cmphex(iid(qts), ==, IIR_THR);
> +
> +    qtest_quit(qts);
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +    g_test_init(&argc, &argv, NULL);
> +    qtest_add_func("/k230-uart/device_probe",       test_device_probe);
> +    qtest_add_func("/k230-uart/init_and_baud",      test_init_and_baud);
> +    qtest_add_func("/k230-uart/tx_rx_datapath",     test_tx_rx_datapath);
> +    qtest_add_func("/k230-uart/thre_interrupt",     test_thre_interrupt);
> +    qtest_add_func("/k230-uart/rx_interrupts",      test_rx_interrupts);
> +    qtest_add_func("/k230-uart/error_interrupts",   test_error_interrupts);
> +    qtest_add_func("/k230-uart/busy_detect",        test_busy_detect);
> +    qtest_add_func("/k230-uart/advanced_features",  test_advanced_features);
> +    return g_test_run();
> +}
> diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
> index 822e0bd286970339fe28127649feb131ce8a81b2..93246d9bf77206e9cebb9d8ade5801f4541d3b8d 100644
> --- a/tests/qtest/meson.build
> +++ b/tests/qtest/meson.build
> @@ -294,7 +294,7 @@ qtests_riscv64 = ['riscv-csr-test'] + \
>     (config_all_devices.has_key('CONFIG_IOMMU_TESTDEV') and
>      config_all_devices.has_key('CONFIG_RISCV_IOMMU') ?
>      ['iommu-riscv-test'] : []) + \
> -  (config_all_devices.has_key('CONFIG_K230') ? ['k230-wdt-test'] : [])
> +  (config_all_devices.has_key('CONFIG_K230') ? ['k230-wdt-test', 'k230-uart-test'] : [])
>   
>   qtests_hexagon = ['boot-serial-test']
>   
> 



  reply	other threads:[~2026-08-05 20:11 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-25  3:52 [PATCH RESEND v2 0/3] riscv: Add K230 DW 8250-compatible UART WX Chen
2026-07-25  3:52 ` [PATCH RESEND v2 1/3] hw/char: add " WX Chen
2026-08-05 20:01   ` Daniel Henrique Barboza
2026-08-07  9:49     ` zhenbaii
2026-07-25  3:52 ` [PATCH RESEND v2 2/3] hw/riscv: k230: connect DW 8250 UART WX Chen
2026-08-05 20:02   ` Daniel Henrique Barboza
2026-07-25  3:52 ` [PATCH RESEND v2 3/3] tests/qtest: add K230 UART test WX Chen
2026-08-05 20:10   ` Daniel Henrique Barboza [this message]
2026-08-07 11:53     ` WX Chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=af3d837c-e7f2-48ce-9b9c-c2ea9e4d8fb8@oss.qualcomm.com \
    --to=daniel.barboza@oss.qualcomm.com \
    --cc=alistair.francis@wdc.com \
    --cc=chao.liu.zevorn@gmail.com \
    --cc=farosas@suse.de \
    --cc=liwei1518@gmail.com \
    --cc=lvivier@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=palmer@dabbelt.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-riscv@nongnu.org \
    --cc=wxchen0913@gmail.com \
    --cc=zhiwei_liu@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.