Message ID | 20211102182519.320319-5-richard.henderson@linaro.org |
---|---|
State | New |
Headers | show |
Series | target/arm patch queue | expand |
Hi, I've sent a new patch set which uses memcpy here. Thank you! On Tue, Nov 2, 2021 at 11:25 AM Richard Henderson < richard.henderson@linaro.org> wrote: > From: Shengtan Mao <stmao@google.com> > > Signed-off-by: Shengtan Mao <stmao@google.com> > Signed-off-by: Hao Wu <wuhaotsh@google.com> > Reviewed-by: Hao Wu <wuhaotsh@google.com> > Reviewed-by: Chris Rauer <crauer@google.com> > Reviewed-by: Tyrone Ting <kfting@nuvoton.com> > Reviewed-by: Peter Maydell <peter.maydell@linaro.org> > Message-Id: <20211008002628.1958285-5-wuhaotsh@google.com> > Signed-off-by: Richard Henderson <richard.henderson@linaro.org> > --- > tests/qtest/libqos/sdhci-cmd.h | 70 ++++++++++++++++++++ > tests/qtest/libqos/sdhci-cmd.c | 116 +++++++++++++++++++++++++++++++++ > tests/qtest/libqos/meson.build | 1 + > 3 files changed, 187 insertions(+) > create mode 100644 tests/qtest/libqos/sdhci-cmd.h > create mode 100644 tests/qtest/libqos/sdhci-cmd.c > > diff --git a/tests/qtest/libqos/sdhci-cmd.h > b/tests/qtest/libqos/sdhci-cmd.h > new file mode 100644 > index 0000000000..64763c5a2a > --- /dev/null > +++ b/tests/qtest/libqos/sdhci-cmd.h > @@ -0,0 +1,70 @@ > +/* > + * MMC Host Controller Commands > + * > + * Copyright (c) 2021 Google LLC > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License as published by the > + * Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, but > WITHOUT > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > + * for more details. > + */ > + > +#include "libqtest.h" > + > +/* more details at hw/sd/sdhci-internal.h */ > +#define SDHC_BLKSIZE 0x04 > +#define SDHC_BLKCNT 0x06 > +#define SDHC_ARGUMENT 0x08 > +#define SDHC_TRNMOD 0x0C > +#define SDHC_CMDREG 0x0E > +#define SDHC_BDATA 0x20 > +#define SDHC_PRNSTS 0x24 > +#define SDHC_BLKGAP 0x2A > +#define SDHC_CLKCON 0x2C > +#define SDHC_SWRST 0x2F > +#define SDHC_CAPAB 0x40 > +#define SDHC_MAXCURR 0x48 > +#define SDHC_HCVER 0xFE > + > +/* TRNSMOD Reg */ > +#define SDHC_TRNS_BLK_CNT_EN 0x0002 > +#define SDHC_TRNS_READ 0x0010 > +#define SDHC_TRNS_WRITE 0x0000 > +#define SDHC_TRNS_MULTI 0x0020 > + > +/* CMD Reg */ > +#define SDHC_CMD_DATA_PRESENT (1 << 5) > +#define SDHC_ALL_SEND_CID (2 << 8) > +#define SDHC_SEND_RELATIVE_ADDR (3 << 8) > +#define SDHC_SELECT_DESELECT_CARD (7 << 8) > +#define SDHC_SEND_CSD (9 << 8) > +#define SDHC_STOP_TRANSMISSION (12 << 8) > +#define SDHC_READ_MULTIPLE_BLOCK (18 << 8) > +#define SDHC_WRITE_MULTIPLE_BLOCK (25 << 8) > +#define SDHC_APP_CMD (55 << 8) > + > +/* SWRST Reg */ > +#define SDHC_RESET_ALL 0x01 > + > +/* CLKCTRL Reg */ > +#define SDHC_CLOCK_INT_EN 0x0001 > +#define SDHC_CLOCK_INT_STABLE 0x0002 > +#define SDHC_CLOCK_SDCLK_EN (1 << 2) > + > +/* Set registers needed to send commands to SD */ > +void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize, > + uint16_t blkcnt, uint32_t argument, uint16_t trnmod, > + uint16_t cmdreg); > + > +/* Read at most 1 block of SD using non-DMA */ > +ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg, > + size_t count); > + > +/* Write at most 1 block of SD using non-DMA */ > +void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg, > + size_t count, size_t blksize); > diff --git a/tests/qtest/libqos/sdhci-cmd.c > b/tests/qtest/libqos/sdhci-cmd.c > new file mode 100644 > index 0000000000..2d9e518341 > --- /dev/null > +++ b/tests/qtest/libqos/sdhci-cmd.c > @@ -0,0 +1,116 @@ > +/* > + * MMC Host Controller Commands > + * > + * Copyright (c) 2021 Google LLC > + * > + * This program is free software; you can redistribute it and/or modify it > + * under the terms of the GNU General Public License as published by the > + * Free Software Foundation; either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program is distributed in the hope that it will be useful, but > WITHOUT > + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or > + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License > + * for more details. > + */ > + > +#include "qemu/osdep.h" > +#include "sdhci-cmd.h" > +#include "libqtest.h" > + > +static ssize_t read_fifo(QTestState *qts, uint64_t reg, char *msg, size_t > count) > +{ > + uint32_t mask = 0xff; > + size_t index = 0; > + uint32_t msg_frag; > + int size; > + while (index < count) { > + size = count - index; > + if (size > 4) { > + size = 4; > + } > + msg_frag = qtest_readl(qts, reg); > + while (size > 0) { > + msg[index] = msg_frag & mask; > + if (msg[index++] == 0) { > + return index; > + } > + msg_frag >>= 8; > + --size; > + } > + } > + return index; > +} > + > +static void write_fifo(QTestState *qts, uint64_t reg, const char *msg, > + size_t count) > +{ > + size_t index = 0; > + uint32_t msg_frag; > + int size; > + int frag_i; > + while (index < count) { > + size = count - index; > + if (size > 4) { > + size = 4; > + } > + msg_frag = 0; > + frag_i = 0; > + while (frag_i < size) { > + msg_frag |= ((uint32_t)msg[index++]) << (frag_i * 8); > + ++frag_i; > + } > + qtest_writel(qts, reg, msg_frag); > + } > +} > + > +static void fill_block(QTestState *qts, uint64_t reg, int count) > +{ > + while (--count >= 0) { > + qtest_writel(qts, reg, 0); > + } > +} > + > +void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize, > + uint16_t blkcnt, uint32_t argument, uint16_t trnmod, > + uint16_t cmdreg) > +{ > + qtest_writew(qts, base_addr + SDHC_BLKSIZE, blksize); > + qtest_writew(qts, base_addr + SDHC_BLKCNT, blkcnt); > + qtest_writel(qts, base_addr + SDHC_ARGUMENT, argument); > + qtest_writew(qts, base_addr + SDHC_TRNMOD, trnmod); > + qtest_writew(qts, base_addr + SDHC_CMDREG, cmdreg); > +} > + > +ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg, > + size_t count) > +{ > + sdhci_cmd_regs(qts, base_addr, count, 1, 0, > + SDHC_TRNS_MULTI | SDHC_TRNS_READ | > SDHC_TRNS_BLK_CNT_EN, > + SDHC_READ_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT); > + > + /* read sd fifo_buffer */ > + ssize_t bytes_read = read_fifo(qts, base_addr + SDHC_BDATA, msg, > count); > + > + sdhci_cmd_regs(qts, base_addr, 0, 0, 0, > + SDHC_TRNS_MULTI | SDHC_TRNS_READ | > SDHC_TRNS_BLK_CNT_EN, > + SDHC_STOP_TRANSMISSION); > + > + return bytes_read; > +} > + > +void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg, > + size_t count, size_t blksize) > +{ > + sdhci_cmd_regs(qts, base_addr, blksize, 1, 0, > + SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | > SDHC_TRNS_BLK_CNT_EN, > + SDHC_WRITE_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT); > + > + /* write to sd fifo_buffer */ > + write_fifo(qts, base_addr + SDHC_BDATA, msg, count); > + fill_block(qts, base_addr + SDHC_BDATA, (blksize - count) / 4); > + > + sdhci_cmd_regs(qts, base_addr, 0, 0, 0, > + SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | > SDHC_TRNS_BLK_CNT_EN, > + SDHC_STOP_TRANSMISSION); > +} > diff --git a/tests/qtest/libqos/meson.build > b/tests/qtest/libqos/meson.build > index 1f5c8f1053..4af1f04787 100644 > --- a/tests/qtest/libqos/meson.build > +++ b/tests/qtest/libqos/meson.build > @@ -5,6 +5,7 @@ libqos_srcs = files('../libqtest.c', > 'fw_cfg.c', > 'malloc.c', > 'libqos.c', > + 'sdhci-cmd.c', > > # spapr > 'malloc-spapr.c', > -- > 2.25.1 > > <div dir="ltr">Hi,<div><br></div><div>I've sent a new patch set which uses memcpy here. Thank you!</div><div><br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Nov 2, 2021 at 11:25 AM Richard Henderson <<a href="mailto:richard.henderson@linaro.org">richard.henderson@linaro.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">From: Shengtan Mao <<a href="mailto:stmao@google.com" target="_blank">stmao@google.com</a>><br> <br> Signed-off-by: Shengtan Mao <<a href="mailto:stmao@google.com" target="_blank">stmao@google.com</a>><br> Signed-off-by: Hao Wu <<a href="mailto:wuhaotsh@google.com" target="_blank">wuhaotsh@google.com</a>><br> Reviewed-by: Hao Wu <<a href="mailto:wuhaotsh@google.com" target="_blank">wuhaotsh@google.com</a>><br> Reviewed-by: Chris Rauer <<a href="mailto:crauer@google.com" target="_blank">crauer@google.com</a>><br> Reviewed-by: Tyrone Ting <<a href="mailto:kfting@nuvoton.com" target="_blank">kfting@nuvoton.com</a>><br> Reviewed-by: Peter Maydell <<a href="mailto:peter.maydell@linaro.org" target="_blank">peter.maydell@linaro.org</a>><br> Message-Id: <<a href="mailto:20211008002628.1958285-5-wuhaotsh@google.com" target="_blank">20211008002628.1958285-5-wuhaotsh@google.com</a>><br> Signed-off-by: Richard Henderson <<a href="mailto:richard.henderson@linaro.org" target="_blank">richard.henderson@linaro.org</a>><br> ---<br> tests/qtest/libqos/sdhci-cmd.h | 70 ++++++++++++++++++++<br> tests/qtest/libqos/sdhci-cmd.c | 116 +++++++++++++++++++++++++++++++++<br> tests/qtest/libqos/meson.build | 1 +<br> 3 files changed, 187 insertions(+)<br> create mode 100644 tests/qtest/libqos/sdhci-cmd.h<br> create mode 100644 tests/qtest/libqos/sdhci-cmd.c<br> <br> diff --git a/tests/qtest/libqos/sdhci-cmd.h b/tests/qtest/libqos/sdhci-cmd.h<br> new file mode 100644<br> index 0000000000..64763c5a2a<br> --- /dev/null<br> +++ b/tests/qtest/libqos/sdhci-cmd.h<br> @@ -0,0 +1,70 @@<br> +/*<br> + * MMC Host Controller Commands<br> + *<br> + * Copyright (c) 2021 Google LLC<br> + *<br> + * This program is free software; you can redistribute it and/or modify it<br> + * under the terms of the GNU General Public License as published by the<br> + * Free Software Foundation; either version 2 of the License, or<br> + * (at your option) any later version.<br> + *<br> + * This program is distributed in the hope that it will be useful, but WITHOUT<br> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or<br> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License<br> + * for more details.<br> + */<br> +<br> +#include "libqtest.h"<br> +<br> +/* more details at hw/sd/sdhci-internal.h */<br> +#define SDHC_BLKSIZE 0x04<br> +#define SDHC_BLKCNT 0x06<br> +#define SDHC_ARGUMENT 0x08<br> +#define SDHC_TRNMOD 0x0C<br> +#define SDHC_CMDREG 0x0E<br> +#define SDHC_BDATA 0x20<br> +#define SDHC_PRNSTS 0x24<br> +#define SDHC_BLKGAP 0x2A<br> +#define SDHC_CLKCON 0x2C<br> +#define SDHC_SWRST 0x2F<br> +#define SDHC_CAPAB 0x40<br> +#define SDHC_MAXCURR 0x48<br> +#define SDHC_HCVER 0xFE<br> +<br> +/* TRNSMOD Reg */<br> +#define SDHC_TRNS_BLK_CNT_EN 0x0002<br> +#define SDHC_TRNS_READ 0x0010<br> +#define SDHC_TRNS_WRITE 0x0000<br> +#define SDHC_TRNS_MULTI 0x0020<br> +<br> +/* CMD Reg */<br> +#define SDHC_CMD_DATA_PRESENT (1 << 5)<br> +#define SDHC_ALL_SEND_CID (2 << 8)<br> +#define SDHC_SEND_RELATIVE_ADDR (3 << 8)<br> +#define SDHC_SELECT_DESELECT_CARD (7 << 8)<br> +#define SDHC_SEND_CSD (9 << 8)<br> +#define SDHC_STOP_TRANSMISSION (12 << 8)<br> +#define SDHC_READ_MULTIPLE_BLOCK (18 << 8)<br> +#define SDHC_WRITE_MULTIPLE_BLOCK (25 << 8)<br> +#define SDHC_APP_CMD (55 << 8)<br> +<br> +/* SWRST Reg */<br> +#define SDHC_RESET_ALL 0x01<br> +<br> +/* CLKCTRL Reg */<br> +#define SDHC_CLOCK_INT_EN 0x0001<br> +#define SDHC_CLOCK_INT_STABLE 0x0002<br> +#define SDHC_CLOCK_SDCLK_EN (1 << 2)<br> +<br> +/* Set registers needed to send commands to SD */<br> +void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize,<br> + uint16_t blkcnt, uint32_t argument, uint16_t trnmod,<br> + uint16_t cmdreg);<br> +<br> +/* Read at most 1 block of SD using non-DMA */<br> +ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg,<br> + size_t count);<br> +<br> +/* Write at most 1 block of SD using non-DMA */<br> +void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg,<br> + size_t count, size_t blksize);<br> diff --git a/tests/qtest/libqos/sdhci-cmd.c b/tests/qtest/libqos/sdhci-cmd.c<br> new file mode 100644<br> index 0000000000..2d9e518341<br> --- /dev/null<br> +++ b/tests/qtest/libqos/sdhci-cmd.c<br> @@ -0,0 +1,116 @@<br> +/*<br> + * MMC Host Controller Commands<br> + *<br> + * Copyright (c) 2021 Google LLC<br> + *<br> + * This program is free software; you can redistribute it and/or modify it<br> + * under the terms of the GNU General Public License as published by the<br> + * Free Software Foundation; either version 2 of the License, or<br> + * (at your option) any later version.<br> + *<br> + * This program is distributed in the hope that it will be useful, but WITHOUT<br> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or<br> + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License<br> + * for more details.<br> + */<br> +<br> +#include "qemu/osdep.h"<br> +#include "sdhci-cmd.h"<br> +#include "libqtest.h"<br> +<br> +static ssize_t read_fifo(QTestState *qts, uint64_t reg, char *msg, size_t count)<br> +{<br> + uint32_t mask = 0xff;<br> + size_t index = 0;<br> + uint32_t msg_frag;<br> + int size;<br> + while (index < count) {<br> + size = count - index;<br> + if (size > 4) {<br> + size = 4;<br> + }<br> + msg_frag = qtest_readl(qts, reg);<br> + while (size > 0) {<br> + msg[index] = msg_frag & mask;<br> + if (msg[index++] == 0) {<br> + return index;<br> + }<br> + msg_frag >>= 8;<br> + --size;<br> + }<br> + }<br> + return index;<br> +}<br> +<br> +static void write_fifo(QTestState *qts, uint64_t reg, const char *msg,<br> + size_t count)<br> +{<br> + size_t index = 0;<br> + uint32_t msg_frag;<br> + int size;<br> + int frag_i;<br> + while (index < count) {<br> + size = count - index;<br> + if (size > 4) {<br> + size = 4;<br> + }<br> + msg_frag = 0;<br> + frag_i = 0;<br> + while (frag_i < size) {<br> + msg_frag |= ((uint32_t)msg[index++]) << (frag_i * 8);<br> + ++frag_i;<br> + }<br> + qtest_writel(qts, reg, msg_frag);<br> + }<br> +}<br> +<br> +static void fill_block(QTestState *qts, uint64_t reg, int count)<br> +{<br> + while (--count >= 0) {<br> + qtest_writel(qts, reg, 0);<br> + }<br> +}<br> +<br> +void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize,<br> + uint16_t blkcnt, uint32_t argument, uint16_t trnmod,<br> + uint16_t cmdreg)<br> +{<br> + qtest_writew(qts, base_addr + SDHC_BLKSIZE, blksize);<br> + qtest_writew(qts, base_addr + SDHC_BLKCNT, blkcnt);<br> + qtest_writel(qts, base_addr + SDHC_ARGUMENT, argument);<br> + qtest_writew(qts, base_addr + SDHC_TRNMOD, trnmod);<br> + qtest_writew(qts, base_addr + SDHC_CMDREG, cmdreg);<br> +}<br> +<br> +ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg,<br> + size_t count)<br> +{<br> + sdhci_cmd_regs(qts, base_addr, count, 1, 0,<br> + SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN,<br> + SDHC_READ_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT);<br> +<br> + /* read sd fifo_buffer */<br> + ssize_t bytes_read = read_fifo(qts, base_addr + SDHC_BDATA, msg, count);<br> +<br> + sdhci_cmd_regs(qts, base_addr, 0, 0, 0,<br> + SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN,<br> + SDHC_STOP_TRANSMISSION);<br> +<br> + return bytes_read;<br> +}<br> +<br> +void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg,<br> + size_t count, size_t blksize)<br> +{<br> + sdhci_cmd_regs(qts, base_addr, blksize, 1, 0,<br> + SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN,<br> + SDHC_WRITE_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT);<br> +<br> + /* write to sd fifo_buffer */<br> + write_fifo(qts, base_addr + SDHC_BDATA, msg, count);<br> + fill_block(qts, base_addr + SDHC_BDATA, (blksize - count) / 4);<br> +<br> + sdhci_cmd_regs(qts, base_addr, 0, 0, 0,<br> + SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN,<br> + SDHC_STOP_TRANSMISSION);<br> +}<br> diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build<br> index 1f5c8f1053..4af1f04787 100644<br> --- a/tests/qtest/libqos/meson.build<br> +++ b/tests/qtest/libqos/meson.build<br> @@ -5,6 +5,7 @@ libqos_srcs = files('../libqtest.c',<br> 'fw_cfg.c',<br> 'malloc.c',<br> 'libqos.c',<br> + 'sdhci-cmd.c',<br> <br> # spapr<br> 'malloc-spapr.c',<br> -- <br> 2.25.1<br> <br> </blockquote></div>
diff --git a/tests/qtest/libqos/sdhci-cmd.h b/tests/qtest/libqos/sdhci-cmd.h new file mode 100644 index 0000000000..64763c5a2a --- /dev/null +++ b/tests/qtest/libqos/sdhci-cmd.h @@ -0,0 +1,70 @@ +/* + * MMC Host Controller Commands + * + * Copyright (c) 2021 Google LLC + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "libqtest.h" + +/* more details at hw/sd/sdhci-internal.h */ +#define SDHC_BLKSIZE 0x04 +#define SDHC_BLKCNT 0x06 +#define SDHC_ARGUMENT 0x08 +#define SDHC_TRNMOD 0x0C +#define SDHC_CMDREG 0x0E +#define SDHC_BDATA 0x20 +#define SDHC_PRNSTS 0x24 +#define SDHC_BLKGAP 0x2A +#define SDHC_CLKCON 0x2C +#define SDHC_SWRST 0x2F +#define SDHC_CAPAB 0x40 +#define SDHC_MAXCURR 0x48 +#define SDHC_HCVER 0xFE + +/* TRNSMOD Reg */ +#define SDHC_TRNS_BLK_CNT_EN 0x0002 +#define SDHC_TRNS_READ 0x0010 +#define SDHC_TRNS_WRITE 0x0000 +#define SDHC_TRNS_MULTI 0x0020 + +/* CMD Reg */ +#define SDHC_CMD_DATA_PRESENT (1 << 5) +#define SDHC_ALL_SEND_CID (2 << 8) +#define SDHC_SEND_RELATIVE_ADDR (3 << 8) +#define SDHC_SELECT_DESELECT_CARD (7 << 8) +#define SDHC_SEND_CSD (9 << 8) +#define SDHC_STOP_TRANSMISSION (12 << 8) +#define SDHC_READ_MULTIPLE_BLOCK (18 << 8) +#define SDHC_WRITE_MULTIPLE_BLOCK (25 << 8) +#define SDHC_APP_CMD (55 << 8) + +/* SWRST Reg */ +#define SDHC_RESET_ALL 0x01 + +/* CLKCTRL Reg */ +#define SDHC_CLOCK_INT_EN 0x0001 +#define SDHC_CLOCK_INT_STABLE 0x0002 +#define SDHC_CLOCK_SDCLK_EN (1 << 2) + +/* Set registers needed to send commands to SD */ +void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize, + uint16_t blkcnt, uint32_t argument, uint16_t trnmod, + uint16_t cmdreg); + +/* Read at most 1 block of SD using non-DMA */ +ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg, + size_t count); + +/* Write at most 1 block of SD using non-DMA */ +void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg, + size_t count, size_t blksize); diff --git a/tests/qtest/libqos/sdhci-cmd.c b/tests/qtest/libqos/sdhci-cmd.c new file mode 100644 index 0000000000..2d9e518341 --- /dev/null +++ b/tests/qtest/libqos/sdhci-cmd.c @@ -0,0 +1,116 @@ +/* + * MMC Host Controller Commands + * + * Copyright (c) 2021 Google LLC + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "qemu/osdep.h" +#include "sdhci-cmd.h" +#include "libqtest.h" + +static ssize_t read_fifo(QTestState *qts, uint64_t reg, char *msg, size_t count) +{ + uint32_t mask = 0xff; + size_t index = 0; + uint32_t msg_frag; + int size; + while (index < count) { + size = count - index; + if (size > 4) { + size = 4; + } + msg_frag = qtest_readl(qts, reg); + while (size > 0) { + msg[index] = msg_frag & mask; + if (msg[index++] == 0) { + return index; + } + msg_frag >>= 8; + --size; + } + } + return index; +} + +static void write_fifo(QTestState *qts, uint64_t reg, const char *msg, + size_t count) +{ + size_t index = 0; + uint32_t msg_frag; + int size; + int frag_i; + while (index < count) { + size = count - index; + if (size > 4) { + size = 4; + } + msg_frag = 0; + frag_i = 0; + while (frag_i < size) { + msg_frag |= ((uint32_t)msg[index++]) << (frag_i * 8); + ++frag_i; + } + qtest_writel(qts, reg, msg_frag); + } +} + +static void fill_block(QTestState *qts, uint64_t reg, int count) +{ + while (--count >= 0) { + qtest_writel(qts, reg, 0); + } +} + +void sdhci_cmd_regs(QTestState *qts, uint64_t base_addr, uint16_t blksize, + uint16_t blkcnt, uint32_t argument, uint16_t trnmod, + uint16_t cmdreg) +{ + qtest_writew(qts, base_addr + SDHC_BLKSIZE, blksize); + qtest_writew(qts, base_addr + SDHC_BLKCNT, blkcnt); + qtest_writel(qts, base_addr + SDHC_ARGUMENT, argument); + qtest_writew(qts, base_addr + SDHC_TRNMOD, trnmod); + qtest_writew(qts, base_addr + SDHC_CMDREG, cmdreg); +} + +ssize_t sdhci_read_cmd(QTestState *qts, uint64_t base_addr, char *msg, + size_t count) +{ + sdhci_cmd_regs(qts, base_addr, count, 1, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN, + SDHC_READ_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT); + + /* read sd fifo_buffer */ + ssize_t bytes_read = read_fifo(qts, base_addr + SDHC_BDATA, msg, count); + + sdhci_cmd_regs(qts, base_addr, 0, 0, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_READ | SDHC_TRNS_BLK_CNT_EN, + SDHC_STOP_TRANSMISSION); + + return bytes_read; +} + +void sdhci_write_cmd(QTestState *qts, uint64_t base_addr, const char *msg, + size_t count, size_t blksize) +{ + sdhci_cmd_regs(qts, base_addr, blksize, 1, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN, + SDHC_WRITE_MULTIPLE_BLOCK | SDHC_CMD_DATA_PRESENT); + + /* write to sd fifo_buffer */ + write_fifo(qts, base_addr + SDHC_BDATA, msg, count); + fill_block(qts, base_addr + SDHC_BDATA, (blksize - count) / 4); + + sdhci_cmd_regs(qts, base_addr, 0, 0, 0, + SDHC_TRNS_MULTI | SDHC_TRNS_WRITE | SDHC_TRNS_BLK_CNT_EN, + SDHC_STOP_TRANSMISSION); +} diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build index 1f5c8f1053..4af1f04787 100644 --- a/tests/qtest/libqos/meson.build +++ b/tests/qtest/libqos/meson.build @@ -5,6 +5,7 @@ libqos_srcs = files('../libqtest.c', 'fw_cfg.c', 'malloc.c', 'libqos.c', + 'sdhci-cmd.c', # spapr 'malloc-spapr.c',