Add nuvoton sd module for NPCM7XX
Add gdb-xml for MVE More uses of tcg_constant_* in target/arm Fix parameter naming for default-bus-bypass-iommu Ignore cache operations to mmio in HVF -----BEGIN PGP SIGNATURE----- iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmGBgjkdHHJpY2hhcmQu aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV8sAAgAsHaW2sHH/W4TzCwl DfqFar4u047Q+ZtQHjNehGHF9Bxp4NS4A0qL52vk0hVoqeWlyF1N29MOnewgVDqY q1x+uxJtG9xjTse7oEEshEEFF/7J8eB8dN4E78TFn/6IhvVhGiUeeRu29s44Ot6N E2KABcXfd+4gEdqhepLGEbi5n0TnA8ARmmeffZNWVEbsxQjHnMQQYmqGmllB3xV3 qPpnp3avvD1015zMwrLVmlDO+tSRr/1bed7k3k26ebga2B/zitxcpXFNCDlgePx0 LNT5QYvBDpE7HOruGQjf4iXPJHfYw5VMtopK7K++rY9KWiJgBVSjQUcB462sdCPk wNAp0g== =vlZ5 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/rth/tags/pull-arm-20211102-2' into staging Add nuvoton sd module for NPCM7XX Add gdb-xml for MVE More uses of tcg_constant_* in target/arm Fix parameter naming for default-bus-bypass-iommu Ignore cache operations to mmio in HVF # gpg: Signature made Tue 02 Nov 2021 02:23:53 PM EDT # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [ultimate] * remotes/rth/tags/pull-arm-20211102-2: hvf: arm: Ignore cache operations on MMIO hw/arm/virt: Rename default_bus_bypass_iommu target/arm: Use tcg_constant_i32() in gen_rev16() target/arm: Use tcg_constant_i64() in do_sat_addsub_64() target/arm: Use the constant variant of store_cpu_field() when possible target/arm: Introduce store_cpu_field_constant() helper target/arm: Use tcg_constant_i32() in op_smlad() target/arm: Advertise MVE to gdb when present tests/qtest/libqos: add SDHCI commands hw/arm: Attach MMC to quanta-gbs-bmc hw/arm: Add Nuvoton SD module to board hw/sd: add nuvoton MMC Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
cc23377516
@ -1,5 +1,5 @@
|
||||
TARGET_ARCH=aarch64
|
||||
TARGET_BASE_ARCH=arm
|
||||
TARGET_SUPPORTS_MTTCG=y
|
||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
|
||||
TARGET_XML_FILES= gdb-xml/aarch64-core.xml gdb-xml/aarch64-fpu.xml gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
|
||||
TARGET_NEED_FDT=y
|
||||
|
@ -1,6 +1,6 @@
|
||||
TARGET_ARCH=arm
|
||||
TARGET_SYSTBL_ABI=common,oabi
|
||||
TARGET_SYSTBL=syscall.tbl
|
||||
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
|
||||
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
|
||||
TARGET_HAS_BFLT=y
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
@ -1,4 +1,4 @@
|
||||
TARGET_ARCH=arm
|
||||
TARGET_SUPPORTS_MTTCG=y
|
||||
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
|
||||
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
|
||||
TARGET_NEED_FDT=y
|
||||
|
@ -2,6 +2,6 @@ TARGET_ARCH=arm
|
||||
TARGET_SYSTBL_ABI=common,oabi
|
||||
TARGET_SYSTBL=syscall.tbl
|
||||
TARGET_WORDS_BIGENDIAN=y
|
||||
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml
|
||||
TARGET_XML_FILES= gdb-xml/arm-core.xml gdb-xml/arm-vfp.xml gdb-xml/arm-vfp3.xml gdb-xml/arm-vfp-sysregs.xml gdb-xml/arm-neon.xml gdb-xml/arm-m-profile.xml gdb-xml/arm-m-profile-mve.xml
|
||||
TARGET_HAS_BFLT=y
|
||||
CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
|
||||
|
19
gdb-xml/arm-m-profile-mve.xml
Normal file
19
gdb-xml/arm-m-profile-mve.xml
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- Copyright (C) 2021 Free Software Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. -->
|
||||
|
||||
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
|
||||
<feature name="org.gnu.gdb.arm.m-profile-mve">
|
||||
<flags id="vpr_reg" size="4">
|
||||
<!-- ARMv8.1-M and MVE: Unprivileged and privileged Access. -->
|
||||
<field name="P0" start="0" end="15"/>
|
||||
<!-- ARMv8.1-M: Privileged Access only. -->
|
||||
<field name="MASK01" start="16" end="19"/>
|
||||
<!-- ARMv8.1-M: Privileged Access only. -->
|
||||
<field name="MASK23" start="20" end="23"/>
|
||||
</flags>
|
||||
<reg name="vpr" bitsize="32" type="vpr_reg"/>
|
||||
</feature>
|
@ -63,6 +63,8 @@
|
||||
#define NPCM7XX_ROM_BA (0xffff0000)
|
||||
#define NPCM7XX_ROM_SZ (64 * KiB)
|
||||
|
||||
/* SDHCI Modules */
|
||||
#define NPCM7XX_MMC_BA (0xf0842000)
|
||||
|
||||
/* Clock configuration values to be fixed up when bypassing bootloader */
|
||||
|
||||
@ -83,6 +85,7 @@ enum NPCM7xxInterrupt {
|
||||
NPCM7XX_UART3_IRQ,
|
||||
NPCM7XX_EMC1RX_IRQ = 15,
|
||||
NPCM7XX_EMC1TX_IRQ,
|
||||
NPCM7XX_MMC_IRQ = 26,
|
||||
NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
|
||||
NPCM7XX_TIMER1_IRQ,
|
||||
NPCM7XX_TIMER2_IRQ,
|
||||
@ -443,6 +446,8 @@ static void npcm7xx_init(Object *obj)
|
||||
for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
|
||||
object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
|
||||
}
|
||||
|
||||
object_initialize_child(obj, "mmc", &s->mmc, TYPE_NPCM7XX_SDHCI);
|
||||
}
|
||||
|
||||
static void npcm7xx_realize(DeviceState *dev, Error **errp)
|
||||
@ -707,6 +712,12 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
|
||||
&error_abort);
|
||||
memory_region_add_subregion(get_system_memory(), NPCM7XX_ROM_BA, &s->irom);
|
||||
|
||||
/* SDHCI */
|
||||
sysbus_realize(SYS_BUS_DEVICE(&s->mmc), &error_abort);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->mmc), 0, NPCM7XX_MMC_BA);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->mmc), 0,
|
||||
npcm7xx_irq(s, NPCM7XX_MMC_IRQ));
|
||||
|
||||
create_unimplemented_device("npcm7xx.shm", 0xc0001000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.vdmx", 0xe0800000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.pcierc", 0xe1000000, 64 * KiB);
|
||||
@ -736,7 +747,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
|
||||
create_unimplemented_device("npcm7xx.usbd[8]", 0xf0838000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.usbd[9]", 0xf0839000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.sd", 0xf0840000, 8 * KiB);
|
||||
create_unimplemented_device("npcm7xx.mmc", 0xf0842000, 8 * KiB);
|
||||
create_unimplemented_device("npcm7xx.pcimbx", 0xf0848000, 512 * KiB);
|
||||
create_unimplemented_device("npcm7xx.aes", 0xf0858000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.des", 0xf0859000, 4 * KiB);
|
||||
|
@ -27,6 +27,9 @@
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/datadir.h"
|
||||
#include "qemu/units.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
|
||||
#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
|
||||
#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
|
||||
@ -81,6 +84,22 @@ static void npcm7xx_connect_dram(NPCM7xxState *soc, MemoryRegion *dram)
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
static void sdhci_attach_drive(SDHCIState *sdhci)
|
||||
{
|
||||
DriveInfo *di = drive_get_next(IF_SD);
|
||||
BlockBackend *blk = di ? blk_by_legacy_dinfo(di) : NULL;
|
||||
|
||||
BusState *bus = qdev_get_child_bus(DEVICE(sdhci), "sd-bus");
|
||||
if (bus == NULL) {
|
||||
error_report("No SD bus found in SOC object");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
DeviceState *carddev = qdev_new(TYPE_SD_CARD);
|
||||
qdev_prop_set_drive_err(carddev, "drive", blk, &error_fatal);
|
||||
qdev_realize_and_unref(carddev, bus, &error_fatal);
|
||||
}
|
||||
|
||||
static NPCM7xxState *npcm7xx_create_soc(MachineState *machine,
|
||||
uint32_t hw_straps)
|
||||
{
|
||||
@ -355,6 +374,7 @@ static void quanta_gbs_init(MachineState *machine)
|
||||
drive_get(IF_MTD, 0, 0));
|
||||
|
||||
quanta_gbs_i2c_init(soc);
|
||||
sdhci_attach_drive(&soc->mmc.sdhci);
|
||||
npcm7xx_load_kernel(machine, soc);
|
||||
}
|
||||
|
||||
|
@ -2737,10 +2737,10 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
|
||||
"Set the IOMMU type. "
|
||||
"Valid values are none and smmuv3");
|
||||
|
||||
object_class_property_add_bool(oc, "default_bus_bypass_iommu",
|
||||
object_class_property_add_bool(oc, "default-bus-bypass-iommu",
|
||||
virt_get_default_bus_bypass_iommu,
|
||||
virt_set_default_bus_bypass_iommu);
|
||||
object_class_property_set_description(oc, "default_bus_bypass_iommu",
|
||||
object_class_property_set_description(oc, "default-bus-bypass-iommu",
|
||||
"Set on/off to enable/disable "
|
||||
"bypass_iommu for default root bus");
|
||||
|
||||
|
@ -9,4 +9,5 @@ softmmu_ss.add(when: 'CONFIG_PXA2XX', if_true: files('pxa2xx_mmci.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_RASPI', if_true: files('bcm2835_sdhost.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_sdhci.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sdhost.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_sdhci.c'))
|
||||
softmmu_ss.add(when: 'CONFIG_CADENCE_SDHCI', if_true: files('cadence_sdhci.c'))
|
||||
|
182
hw/sd/npcm7xx_sdhci.c
Normal file
182
hw/sd/npcm7xx_sdhci.c
Normal file
@ -0,0 +1,182 @@
|
||||
/*
|
||||
* NPCM7xx SD-3.0 / eMMC-4.51 Host Controller
|
||||
*
|
||||
* 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 "hw/sd/npcm7xx_sdhci.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "sdhci-internal.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
static uint64_t npcm7xx_sdhci_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
{
|
||||
NPCM7xxSDHCIState *s = opaque;
|
||||
uint64_t val = 0;
|
||||
|
||||
switch (addr) {
|
||||
case NPCM7XX_PRSTVALS_0:
|
||||
case NPCM7XX_PRSTVALS_1:
|
||||
case NPCM7XX_PRSTVALS_2:
|
||||
case NPCM7XX_PRSTVALS_3:
|
||||
case NPCM7XX_PRSTVALS_4:
|
||||
case NPCM7XX_PRSTVALS_5:
|
||||
val = s->regs.prstvals[(addr - NPCM7XX_PRSTVALS_0) / 2];
|
||||
break;
|
||||
case NPCM7XX_BOOTTOCTRL:
|
||||
val = s->regs.boottoctrl;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "SDHCI read of nonexistent reg: 0x%02"
|
||||
HWADDR_PRIx, addr);
|
||||
break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void npcm7xx_sdhci_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
unsigned int size)
|
||||
{
|
||||
NPCM7xxSDHCIState *s = opaque;
|
||||
|
||||
switch (addr) {
|
||||
case NPCM7XX_BOOTTOCTRL:
|
||||
s->regs.boottoctrl = val;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "SDHCI write of nonexistent reg: 0x%02"
|
||||
HWADDR_PRIx, addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool npcm7xx_sdhci_check_mem_op(void *opaque, hwaddr addr,
|
||||
unsigned size, bool is_write,
|
||||
MemTxAttrs attrs)
|
||||
{
|
||||
switch (addr) {
|
||||
case NPCM7XX_PRSTVALS_0:
|
||||
case NPCM7XX_PRSTVALS_1:
|
||||
case NPCM7XX_PRSTVALS_2:
|
||||
case NPCM7XX_PRSTVALS_3:
|
||||
case NPCM7XX_PRSTVALS_4:
|
||||
case NPCM7XX_PRSTVALS_5:
|
||||
/* RO Word */
|
||||
return !is_write && size == 2;
|
||||
case NPCM7XX_BOOTTOCTRL:
|
||||
/* R/W Dword */
|
||||
return size == 4;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps npcm7xx_sdhci_ops = {
|
||||
.read = npcm7xx_sdhci_read,
|
||||
.write = npcm7xx_sdhci_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 1,
|
||||
.max_access_size = 4,
|
||||
.unaligned = false,
|
||||
.accepts = npcm7xx_sdhci_check_mem_op,
|
||||
},
|
||||
};
|
||||
|
||||
static void npcm7xx_sdhci_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
NPCM7xxSDHCIState *s = NPCM7XX_SDHCI(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
SysBusDevice *sbd_sdhci = SYS_BUS_DEVICE(&s->sdhci);
|
||||
|
||||
memory_region_init(&s->container, OBJECT(s),
|
||||
"npcm7xx.sdhci-container", 0x1000);
|
||||
sysbus_init_mmio(sbd, &s->container);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &npcm7xx_sdhci_ops, s,
|
||||
TYPE_NPCM7XX_SDHCI, NPCM7XX_SDHCI_REGSIZE);
|
||||
memory_region_add_subregion_overlap(&s->container, NPCM7XX_PRSTVALS,
|
||||
&s->iomem, 1);
|
||||
|
||||
sysbus_realize(sbd_sdhci, errp);
|
||||
memory_region_add_subregion(&s->container, 0,
|
||||
sysbus_mmio_get_region(sbd_sdhci, 0));
|
||||
|
||||
/* propagate irq and "sd-bus" from generic-sdhci */
|
||||
sysbus_pass_irq(sbd, sbd_sdhci);
|
||||
s->bus = qdev_get_child_bus(DEVICE(sbd_sdhci), "sd-bus");
|
||||
|
||||
/* Set the read only preset values. */
|
||||
memset(s->regs.prstvals, 0, sizeof(s->regs.prstvals));
|
||||
s->regs.prstvals[0] = NPCM7XX_PRSTVALS_0_RESET;
|
||||
s->regs.prstvals[1] = NPCM7XX_PRSTVALS_1_RESET;
|
||||
s->regs.prstvals[3] = NPCM7XX_PRSTVALS_3_RESET;
|
||||
}
|
||||
|
||||
static void npcm7xx_sdhci_reset(DeviceState *dev)
|
||||
{
|
||||
NPCM7xxSDHCIState *s = NPCM7XX_SDHCI(dev);
|
||||
device_cold_reset(DEVICE(&s->sdhci));
|
||||
s->regs.boottoctrl = 0;
|
||||
|
||||
s->sdhci.prnsts = NPCM7XX_PRSNTS_RESET;
|
||||
s->sdhci.blkgap = NPCM7XX_BLKGAP_RESET;
|
||||
s->sdhci.capareg = NPCM7XX_CAPAB_RESET;
|
||||
s->sdhci.maxcurr = NPCM7XX_MAXCURR_RESET;
|
||||
s->sdhci.version = NPCM7XX_HCVER_RESET;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_npcm7xx_sdhci = {
|
||||
.name = TYPE_NPCM7XX_SDHCI,
|
||||
.version_id = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(regs.boottoctrl, NPCM7xxSDHCIState),
|
||||
VMSTATE_END_OF_LIST(),
|
||||
},
|
||||
};
|
||||
|
||||
static void npcm7xx_sdhci_class_init(ObjectClass *classp, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(classp);
|
||||
|
||||
dc->desc = "NPCM7xx SD/eMMC Host Controller";
|
||||
dc->realize = npcm7xx_sdhci_realize;
|
||||
dc->reset = npcm7xx_sdhci_reset;
|
||||
dc->vmsd = &vmstate_npcm7xx_sdhci;
|
||||
}
|
||||
|
||||
static void npcm7xx_sdhci_instance_init(Object *obj)
|
||||
{
|
||||
NPCM7xxSDHCIState *s = NPCM7XX_SDHCI(obj);
|
||||
|
||||
object_initialize_child(OBJECT(s), "generic-sdhci", &s->sdhci,
|
||||
TYPE_SYSBUS_SDHCI);
|
||||
}
|
||||
|
||||
static TypeInfo npcm7xx_sdhci_info = {
|
||||
.name = TYPE_NPCM7XX_SDHCI,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(NPCM7xxSDHCIState),
|
||||
.instance_init = npcm7xx_sdhci_instance_init,
|
||||
.class_init = npcm7xx_sdhci_class_init,
|
||||
};
|
||||
|
||||
static void npcm7xx_sdhci_register_types(void)
|
||||
{
|
||||
type_register_static(&npcm7xx_sdhci_info);
|
||||
}
|
||||
|
||||
type_init(npcm7xx_sdhci_register_types)
|
@ -35,6 +35,7 @@
|
||||
#include "hw/usb/hcd-ehci.h"
|
||||
#include "hw/usb/hcd-ohci.h"
|
||||
#include "target/arm/cpu.h"
|
||||
#include "hw/sd/npcm7xx_sdhci.h"
|
||||
|
||||
#define NPCM7XX_MAX_NUM_CPUS (2)
|
||||
|
||||
@ -103,6 +104,7 @@ typedef struct NPCM7xxState {
|
||||
OHCISysBusState ohci;
|
||||
NPCM7xxFIUState fiu[2];
|
||||
NPCM7xxEMCState emc[2];
|
||||
NPCM7xxSDHCIState mmc;
|
||||
} NPCM7xxState;
|
||||
|
||||
#define TYPE_NPCM7XX "npcm7xx"
|
||||
|
65
include/hw/sd/npcm7xx_sdhci.h
Normal file
65
include/hw/sd/npcm7xx_sdhci.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* NPCM7xx SD-3.0 / eMMC-4.51 Host Controller
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef NPCM7XX_SDHCI_H
|
||||
#define NPCM7XX_SDHCI_H
|
||||
|
||||
#include "hw/sd/sdhci.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define TYPE_NPCM7XX_SDHCI "npcm7xx.sdhci"
|
||||
#define NPCM7XX_PRSTVALS_SIZE 6
|
||||
#define NPCM7XX_PRSTVALS 0x60
|
||||
#define NPCM7XX_PRSTVALS_0 0x0
|
||||
#define NPCM7XX_PRSTVALS_1 0x2
|
||||
#define NPCM7XX_PRSTVALS_2 0x4
|
||||
#define NPCM7XX_PRSTVALS_3 0x6
|
||||
#define NPCM7XX_PRSTVALS_4 0x8
|
||||
#define NPCM7XX_PRSTVALS_5 0xA
|
||||
#define NPCM7XX_BOOTTOCTRL 0x10
|
||||
#define NPCM7XX_SDHCI_REGSIZE 0x20
|
||||
|
||||
#define NPCM7XX_PRSNTS_RESET 0x04A00000
|
||||
#define NPCM7XX_BLKGAP_RESET 0x80
|
||||
#define NPCM7XX_CAPAB_RESET 0x0100200161EE0399
|
||||
#define NPCM7XX_MAXCURR_RESET 0x0000000000000005
|
||||
#define NPCM7XX_HCVER_RESET 0x1002
|
||||
|
||||
#define NPCM7XX_PRSTVALS_0_RESET 0x0040
|
||||
#define NPCM7XX_PRSTVALS_1_RESET 0x0001
|
||||
#define NPCM7XX_PRSTVALS_3_RESET 0x0001
|
||||
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxSDHCIState, NPCM7XX_SDHCI)
|
||||
|
||||
typedef struct NPCM7xxRegs {
|
||||
/* Preset Values Register Field, read-only */
|
||||
uint16_t prstvals[NPCM7XX_PRSTVALS_SIZE];
|
||||
/* Boot Timeout Control Register, read-write */
|
||||
uint32_t boottoctrl;
|
||||
} NPCM7xxRegisters;
|
||||
|
||||
typedef struct NPCM7xxSDHCIState {
|
||||
SysBusDevice parent;
|
||||
|
||||
MemoryRegion container;
|
||||
MemoryRegion iomem;
|
||||
BusState *bus;
|
||||
NPCM7xxRegisters regs;
|
||||
|
||||
SDHCIState sdhci;
|
||||
} NPCM7xxSDHCIState;
|
||||
|
||||
#endif /* NPCM7XX_SDHCI_H */
|
@ -199,6 +199,27 @@ static int vfp_gdb_set_sysreg(CPUARMState *env, uint8_t *buf, int reg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mve_gdb_get_reg(CPUARMState *env, GByteArray *buf, int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0:
|
||||
return gdb_get_reg32(buf, env->v7m.vpr);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int mve_gdb_set_reg(CPUARMState *env, uint8_t *buf, int reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0:
|
||||
env->v7m.vpr = ldl_p(buf);
|
||||
return 4;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* arm_get/set_gdb_*: get/set a gdb register
|
||||
* @env: the CPU state
|
||||
@ -468,6 +489,10 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
|
||||
2, "arm-vfp-sysregs.xml", 0);
|
||||
}
|
||||
}
|
||||
if (cpu_isar_feature(aa32_mve, cpu)) {
|
||||
gdb_register_coprocessor(cs, mve_gdb_get_reg, mve_gdb_set_reg,
|
||||
1, "arm-m-profile-mve.xml", 0);
|
||||
}
|
||||
gdb_register_coprocessor(cs, arm_gdb_get_sysreg, arm_gdb_set_sysreg,
|
||||
arm_gen_dynamic_sysreg_xml(cs, cs->gdb_num_regs),
|
||||
"system-registers.xml", 0);
|
||||
|
@ -1150,12 +1150,19 @@ int hvf_vcpu_exec(CPUState *cpu)
|
||||
uint32_t sas = (syndrome >> 22) & 3;
|
||||
uint32_t len = 1 << sas;
|
||||
uint32_t srt = (syndrome >> 16) & 0x1f;
|
||||
uint32_t cm = (syndrome >> 8) & 0x1;
|
||||
uint64_t val = 0;
|
||||
|
||||
trace_hvf_data_abort(env->pc, hvf_exit->exception.virtual_address,
|
||||
hvf_exit->exception.physical_address, isv,
|
||||
iswrite, s1ptw, len, srt);
|
||||
|
||||
if (cm) {
|
||||
/* We don't cache MMIO regions */
|
||||
advance_pc = true;
|
||||
break;
|
||||
}
|
||||
|
||||
assert(isv);
|
||||
|
||||
if (iswrite) {
|
||||
|
@ -70,6 +70,9 @@ static inline void store_cpu_offset(TCGv_i32 var, int offset)
|
||||
#define store_cpu_field(var, name) \
|
||||
store_cpu_offset(var, offsetof(CPUARMState, name))
|
||||
|
||||
#define store_cpu_field_constant(val, name) \
|
||||
tcg_gen_st_i32(tcg_constant_i32(val), cpu_env, offsetof(CPUARMState, name))
|
||||
|
||||
/* Create a new temporary and set it to the value of a CPU register. */
|
||||
static inline TCGv_i32 load_reg(DisasContext *s, int reg)
|
||||
{
|
||||
|
@ -1943,20 +1943,20 @@ static void do_sat_addsub_32(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
|
||||
static void do_sat_addsub_64(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
|
||||
{
|
||||
TCGv_i64 t0 = tcg_temp_new_i64();
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
TCGv_i64 t2;
|
||||
|
||||
if (u) {
|
||||
if (d) {
|
||||
tcg_gen_sub_i64(t0, reg, val);
|
||||
tcg_gen_movi_i64(t1, 0);
|
||||
tcg_gen_movcond_i64(TCG_COND_LTU, reg, reg, val, t1, t0);
|
||||
t2 = tcg_constant_i64(0);
|
||||
tcg_gen_movcond_i64(TCG_COND_LTU, reg, reg, val, t2, t0);
|
||||
} else {
|
||||
tcg_gen_add_i64(t0, reg, val);
|
||||
tcg_gen_movi_i64(t1, -1);
|
||||
tcg_gen_movcond_i64(TCG_COND_LTU, reg, t0, reg, t1, t0);
|
||||
t2 = tcg_constant_i64(-1);
|
||||
tcg_gen_movcond_i64(TCG_COND_LTU, reg, t0, reg, t2, t0);
|
||||
}
|
||||
} else {
|
||||
TCGv_i64 t1 = tcg_temp_new_i64();
|
||||
if (d) {
|
||||
/* Detect signed overflow for subtraction. */
|
||||
tcg_gen_xor_i64(t0, reg, val);
|
||||
@ -1966,7 +1966,7 @@ static void do_sat_addsub_64(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
|
||||
|
||||
/* Bound the result. */
|
||||
tcg_gen_movi_i64(reg, INT64_MIN);
|
||||
t2 = tcg_const_i64(0);
|
||||
t2 = tcg_constant_i64(0);
|
||||
tcg_gen_movcond_i64(TCG_COND_LT, reg, t0, t2, reg, t1);
|
||||
} else {
|
||||
/* Detect signed overflow for addition. */
|
||||
@ -1977,13 +1977,12 @@ static void do_sat_addsub_64(TCGv_i64 reg, TCGv_i64 val, bool u, bool d)
|
||||
|
||||
/* Bound the result. */
|
||||
tcg_gen_movi_i64(t1, INT64_MAX);
|
||||
t2 = tcg_const_i64(0);
|
||||
t2 = tcg_constant_i64(0);
|
||||
tcg_gen_movcond_i64(TCG_COND_LT, reg, t0, t2, t1, reg);
|
||||
}
|
||||
tcg_temp_free_i64(t2);
|
||||
tcg_temp_free_i64(t1);
|
||||
}
|
||||
tcg_temp_free_i64(t0);
|
||||
tcg_temp_free_i64(t1);
|
||||
}
|
||||
|
||||
/* Similarly with a vector and a scalar operand. */
|
||||
|
@ -364,8 +364,7 @@ void clear_eci_state(DisasContext *s)
|
||||
* multiple insn executes.
|
||||
*/
|
||||
if (s->eci) {
|
||||
TCGv_i32 tmp = tcg_const_i32(0);
|
||||
store_cpu_field(tmp, condexec_bits);
|
||||
store_cpu_field_constant(0, condexec_bits);
|
||||
s->eci = 0;
|
||||
}
|
||||
}
|
||||
@ -389,13 +388,12 @@ static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
|
||||
void gen_rev16(TCGv_i32 dest, TCGv_i32 var)
|
||||
{
|
||||
TCGv_i32 tmp = tcg_temp_new_i32();
|
||||
TCGv_i32 mask = tcg_const_i32(0x00ff00ff);
|
||||
TCGv_i32 mask = tcg_constant_i32(0x00ff00ff);
|
||||
tcg_gen_shri_i32(tmp, var, 8);
|
||||
tcg_gen_and_i32(tmp, tmp, mask);
|
||||
tcg_gen_and_i32(var, var, mask);
|
||||
tcg_gen_shli_i32(var, var, 8);
|
||||
tcg_gen_or_i32(dest, var, tmp);
|
||||
tcg_temp_free_i32(mask);
|
||||
tcg_temp_free_i32(tmp);
|
||||
}
|
||||
|
||||
@ -740,9 +738,8 @@ void gen_set_condexec(DisasContext *s)
|
||||
{
|
||||
if (s->condexec_mask) {
|
||||
uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
|
||||
TCGv_i32 tmp = tcg_temp_new_i32();
|
||||
tcg_gen_movi_i32(tmp, val);
|
||||
store_cpu_field(tmp, condexec_bits);
|
||||
|
||||
store_cpu_field_constant(val, condexec_bits);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7849,10 +7846,9 @@ static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
|
||||
t3 = tcg_temp_new_i32();
|
||||
tcg_gen_sari_i32(t3, t1, 31);
|
||||
qf = load_cpu_field(QF);
|
||||
one = tcg_const_i32(1);
|
||||
one = tcg_constant_i32(1);
|
||||
tcg_gen_movcond_i32(TCG_COND_NE, qf, t2, t3, one, qf);
|
||||
store_cpu_field(qf, QF);
|
||||
tcg_temp_free_i32(one);
|
||||
tcg_temp_free_i32(t3);
|
||||
tcg_temp_free_i32(t2);
|
||||
}
|
||||
@ -8363,8 +8359,6 @@ static bool trans_BL(DisasContext *s, arg_i *a)
|
||||
|
||||
static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
|
||||
{
|
||||
TCGv_i32 tmp;
|
||||
|
||||
/*
|
||||
* BLX <imm> would be useless on M-profile; the encoding space
|
||||
* is used for other insns from v8.1M onward, and UNDEFs before that.
|
||||
@ -8378,8 +8372,7 @@ static bool trans_BLX_i(DisasContext *s, arg_BLX_i *a)
|
||||
return false;
|
||||
}
|
||||
tcg_gen_movi_i32(cpu_R[14], s->base.pc_next | s->thumb);
|
||||
tmp = tcg_const_i32(!s->thumb);
|
||||
store_cpu_field(tmp, thumb);
|
||||
store_cpu_field_constant(!s->thumb, thumb);
|
||||
gen_jmp(s, (read_pc(s) & ~3) + a->imm);
|
||||
return true;
|
||||
}
|
||||
@ -8678,7 +8671,6 @@ static bool trans_LCTP(DisasContext *s, arg_LCTP *a)
|
||||
* doesn't cache branch information, all we need to do is reset
|
||||
* FPSCR.LTPSIZE to 4.
|
||||
*/
|
||||
TCGv_i32 ltpsize;
|
||||
|
||||
if (!dc_isar_feature(aa32_lob, s) ||
|
||||
!dc_isar_feature(aa32_mve, s)) {
|
||||
@ -8689,8 +8681,7 @@ static bool trans_LCTP(DisasContext *s, arg_LCTP *a)
|
||||
return true;
|
||||
}
|
||||
|
||||
ltpsize = tcg_const_i32(4);
|
||||
store_cpu_field(ltpsize, v7m.ltpsize);
|
||||
store_cpu_field_constant(4, v7m.ltpsize);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -9488,9 +9479,7 @@ static void arm_tr_tb_start(DisasContextBase *dcbase, CPUState *cpu)
|
||||
/* Reset the conditional execution bits immediately. This avoids
|
||||
complications trying to do it at the end of the block. */
|
||||
if (dc->condexec_mask || dc->condexec_cond) {
|
||||
TCGv_i32 tmp = tcg_temp_new_i32();
|
||||
tcg_gen_movi_i32(tmp, 0);
|
||||
store_cpu_field(tmp, condexec_bits);
|
||||
store_cpu_field_constant(0, condexec_bits);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@ libqos_srcs = files('../libqtest.c',
|
||||
'fw_cfg.c',
|
||||
'malloc.c',
|
||||
'libqos.c',
|
||||
'sdhci-cmd.c',
|
||||
|
||||
# spapr
|
||||
'malloc-spapr.c',
|
||||
|
116
tests/qtest/libqos/sdhci-cmd.c
Normal file
116
tests/qtest/libqos/sdhci-cmd.c
Normal file
@ -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);
|
||||
}
|
70
tests/qtest/libqos/sdhci-cmd.h
Normal file
70
tests/qtest/libqos/sdhci-cmd.h
Normal file
@ -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);
|
Loading…
Reference in New Issue
Block a user