summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Maydell2020-09-03 15:12:48 +0200
committerPeter Maydell2020-09-03 15:12:48 +0200
commit3dd23a4fb8fd72d2220a90a809f213999ffe7f3a (patch)
treee45f68da4c497881301b8b773817810f0acdde02
parentMerge remote-tracking branch 'remotes/nvme/tags/pull-nvme-20200902' into staging (diff)
parenthw: add a number of SPI-flash's of m25p80 family (diff)
downloadqemu-3dd23a4fb8fd72d2220a90a809f213999ffe7f3a.tar.gz
qemu-3dd23a4fb8fd72d2220a90a809f213999ffe7f3a.tar.xz
qemu-3dd23a4fb8fd72d2220a90a809f213999ffe7f3a.zip
Merge remote-tracking branch 'remotes/legoater/tags/pull-aspeed-20200901' into staging
Various fixes of Aspeed machines : * New Supermicro X11 BMC machine (Erik) * Fixed valid access size on AST2400 SCU * Improved robustness of the ftgmac100 model. * New flash models in m25p80 (Igor) * Fixed reset sequence of SDHCI/eMMC controllers * Improved support of the AST2600 SDMC (Joel) * Couple of SMC cleanups # gpg: Signature made Tue 01 Sep 2020 13:39:20 BST # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * remotes/legoater/tags/pull-aspeed-20200901: hw: add a number of SPI-flash's of m25p80 family arm: aspeed: add strap define `25HZ` of AST2500 aspeed/smc: Open AHB window of the second chip of the AST2600 FMC controller aspeed/sdmc: Simplify calculation of RAM bits aspeed/sdmc: Allow writes to unprotected registers aspeed/sdmc: Perform memory training ftgmac100: Improve software reset ftgmac100: Fix integer overflow in ftgmac100_do_tx() ftgmac100: Check for invalid len and address before doing a DMA transfer ftgmac100: Change interrupt status when a DMA error occurs ftgmac100: Fix interrupt status "Packet moved to RX FIFO" ftgmac100: Fix interrupt status "Packet transmitted on ethernet" ftgmac100: Fix registers that can be read aspeed/sdhci: Fix reset sequence aspeed/smc: Fix max_slaves of the legacy SMC device aspeed/smc: Fix MemoryRegionOps definition hw/arm/aspeed: Add board model for Supermicro X11 BMC aspeed/scu: Fix valid access size on AST2400 m25p80: Add support for n25q512ax3 m25p80: Return the JEDEC ID twice for mx25l25635e Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/arm/aspeed.c35
-rw-r--r--hw/block/m25p80.c5
-rw-r--r--hw/misc/aspeed_scu.c9
-rw-r--r--hw/misc/aspeed_sdmc.c125
-rw-r--r--hw/net/ftgmac100.c95
-rw-r--r--hw/sd/aspeed_sdhci.c14
-rw-r--r--hw/ssi/aspeed_smc.c6
-rw-r--r--include/hw/misc/aspeed_scu.h1
-rw-r--r--include/hw/misc/aspeed_sdmc.h13
9 files changed, 208 insertions, 95 deletions
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
index 8109cc6d2d..8bfb1c79dd 100644
--- a/hw/arm/aspeed.c
+++ b/hw/arm/aspeed.c
@@ -57,6 +57,20 @@ struct AspeedMachineState {
SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
+/* TODO: Find the actual hardware value */
+#define SUPERMICROX11_BMC_HW_STRAP1 ( \
+ SCU_AST2400_HW_STRAP_DRAM_SIZE(DRAM_SIZE_128MB) | \
+ SCU_AST2400_HW_STRAP_DRAM_CONFIG(2) | \
+ SCU_AST2400_HW_STRAP_ACPI_DIS | \
+ SCU_AST2400_HW_STRAP_SET_CLK_SOURCE(AST2400_CLK_48M_IN) | \
+ SCU_HW_STRAP_VGA_CLASS_CODE | \
+ SCU_HW_STRAP_LPC_RESET_PIN | \
+ SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_M_S_EN) | \
+ SCU_AST2400_HW_STRAP_SET_CPU_AHB_RATIO(AST2400_CPU_AHB_RATIO_2_1) | \
+ SCU_HW_STRAP_SPI_WIDTH | \
+ SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
+ SCU_AST2400_HW_STRAP_BOOT_MODE(AST2400_SPI_BOOT))
+
/* AST2500 evb hardware value: 0xF100C2E6 */
#define AST2500_EVB_HW_STRAP1 (( \
AST2500_HW_STRAP1_DEFAULTS | \
@@ -603,6 +617,23 @@ static void aspeed_machine_palmetto_class_init(ObjectClass *oc, void *data)
aspeed_soc_num_cpus(amc->soc_name);
};
+static void aspeed_machine_supermicrox11_bmc_class_init(ObjectClass *oc,
+ void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
+
+ mc->desc = "Supermicro X11 BMC (ARM926EJ-S)";
+ amc->soc_name = "ast2400-a1";
+ amc->hw_strap1 = SUPERMICROX11_BMC_HW_STRAP1;
+ amc->fmc_model = "mx25l25635e";
+ amc->spi_model = "mx25l25635e";
+ amc->num_cs = 1;
+ amc->macs_mask = ASPEED_MAC0_ON | ASPEED_MAC1_ON;
+ amc->i2c_init = palmetto_bmc_i2c_init;
+ mc->default_ram_size = 256 * MiB;
+}
+
static void aspeed_machine_ast2500_evb_class_init(ObjectClass *oc, void *data)
{
MachineClass *mc = MACHINE_CLASS(oc);
@@ -732,6 +763,10 @@ static const TypeInfo aspeed_machine_types[] = {
.parent = TYPE_ASPEED_MACHINE,
.class_init = aspeed_machine_palmetto_class_init,
}, {
+ .name = MACHINE_TYPE_NAME("supermicrox11-bmc"),
+ .parent = TYPE_ASPEED_MACHINE,
+ .class_init = aspeed_machine_supermicrox11_bmc_class_init,
+ }, {
.name = MACHINE_TYPE_NAME("ast2500-evb"),
.parent = TYPE_ASPEED_MACHINE,
.class_init = aspeed_machine_ast2500_evb_class_init,
diff --git a/hw/block/m25p80.c b/hw/block/m25p80.c
index 8227088441..15824450cd 100644
--- a/hw/block/m25p80.c
+++ b/hw/block/m25p80.c
@@ -217,8 +217,9 @@ static const FlashPartInfo known_devices[] = {
{ INFO("mx25l6405d", 0xc22017, 0, 64 << 10, 128, 0) },
{ INFO("mx25l12805d", 0xc22018, 0, 64 << 10, 256, 0) },
{ INFO("mx25l12855e", 0xc22618, 0, 64 << 10, 256, 0) },
- { INFO("mx25l25635e", 0xc22019, 0, 64 << 10, 512, 0) },
+ { INFO6("mx25l25635e", 0xc22019, 0xc22019, 64 << 10, 512, 0) },
{ INFO("mx25l25655e", 0xc22619, 0, 64 << 10, 512, 0) },
+ { INFO("mx66l51235f", 0xc2201a, 0, 64 << 10, 1024, ER_4K | ER_32K) },
{ INFO("mx66u51235f", 0xc2253a, 0, 64 << 10, 1024, ER_4K | ER_32K) },
{ INFO("mx66u1g45g", 0xc2253b, 0, 64 << 10, 2048, ER_4K | ER_32K) },
{ INFO("mx66l1g45g", 0xc2201b, 0, 64 << 10, 2048, ER_4K | ER_32K) },
@@ -237,6 +238,8 @@ static const FlashPartInfo known_devices[] = {
{ INFO("n25q128", 0x20ba18, 0, 64 << 10, 256, 0) },
{ INFO("n25q256a", 0x20ba19, 0, 64 << 10, 512, ER_4K) },
{ INFO("n25q512a", 0x20ba20, 0, 64 << 10, 1024, ER_4K) },
+ { INFO("n25q512ax3", 0x20ba20, 0x1000, 64 << 10, 1024, ER_4K) },
+ { INFO("mt25ql512ab", 0x20ba20, 0x1044, 64 << 10, 1024, ER_4K | ER_32K) },
{ INFO_STACKED("n25q00", 0x20ba21, 0x1000, 64 << 10, 2048, ER_4K, 4) },
{ INFO_STACKED("n25q00a", 0x20bb21, 0x1000, 64 << 10, 2048, ER_4K, 4) },
{ INFO_STACKED("mt25ql01g", 0x20ba21, 0x1040, 64 << 10, 2048, ER_4K, 2) },
diff --git a/hw/misc/aspeed_scu.c b/hw/misc/aspeed_scu.c
index ec4fef900e..dc6dd87c22 100644
--- a/hw/misc/aspeed_scu.c
+++ b/hw/misc/aspeed_scu.c
@@ -328,9 +328,10 @@ static const MemoryRegionOps aspeed_ast2400_scu_ops = {
.read = aspeed_scu_read,
.write = aspeed_ast2400_scu_write,
.endianness = DEVICE_LITTLE_ENDIAN,
- .valid.min_access_size = 4,
- .valid.max_access_size = 4,
- .valid.unaligned = false,
+ .valid = {
+ .min_access_size = 1,
+ .max_access_size = 4,
+ },
};
static const MemoryRegionOps aspeed_ast2500_scu_ops = {
@@ -655,7 +656,7 @@ static const uint32_t ast2600_a1_resets[ASPEED_AST2600_SCU_NR_REGS] = {
[AST2600_SYS_RST_CTRL2] = 0xFFFFFFFC,
[AST2600_CLK_STOP_CTRL] = 0xFFFF7F8A,
[AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0,
- [AST2600_SDRAM_HANDSHAKE] = 0x00000040, /* SoC completed DRAM init */
+ [AST2600_SDRAM_HANDSHAKE] = 0x00000000,
[AST2600_HPLL_PARAM] = 0x1000405F,
[AST2600_CHIP_ID0] = 0x1234ABCD,
[AST2600_CHIP_ID1] = 0x88884444,
diff --git a/hw/misc/aspeed_sdmc.c b/hw/misc/aspeed_sdmc.c
index 855848b7d2..08f856cbda 100644
--- a/hw/misc/aspeed_sdmc.c
+++ b/hw/misc/aspeed_sdmc.c
@@ -33,15 +33,28 @@
/* Configuration Register */
#define R_CONF (0x04 / 4)
+/* Interrupt control/status */
+#define R_ISR (0x50 / 4)
+
/* Control/Status Register #1 (ast2500) */
#define R_STATUS1 (0x60 / 4)
#define PHY_BUSY_STATE BIT(0)
#define PHY_PLL_LOCK_STATUS BIT(4)
+/* Reserved */
+#define R_MCR6C (0x6c / 4)
+
#define R_ECC_TEST_CTRL (0x70 / 4)
#define ECC_TEST_FINISHED BIT(12)
#define ECC_TEST_FAIL BIT(13)
+#define R_TEST_START_LEN (0x74 / 4)
+#define R_TEST_FAIL_DQ (0x78 / 4)
+#define R_TEST_INIT_VAL (0x7c / 4)
+#define R_DRAM_SW (0x88 / 4)
+#define R_DRAM_TIME (0x8c / 4)
+#define R_ECC_ERR_INJECT (0xb4 / 4)
+
/*
* Configuration register Ox4 (for Aspeed AST2400 SOC)
*
@@ -113,7 +126,7 @@ static uint64_t aspeed_sdmc_read(void *opaque, hwaddr addr, unsigned size)
if (addr >= ARRAY_SIZE(s->regs)) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
- __func__, addr);
+ __func__, addr * 4);
return 0;
}
@@ -146,57 +159,6 @@ static const MemoryRegionOps aspeed_sdmc_ops = {
.valid.max_access_size = 4,
};
-static int ast2400_rambits(AspeedSDMCState *s)
-{
- switch (s->ram_size >> 20) {
- case 64:
- return ASPEED_SDMC_DRAM_64MB;
- case 128:
- return ASPEED_SDMC_DRAM_128MB;
- case 256:
- return ASPEED_SDMC_DRAM_256MB;
- case 512:
- return ASPEED_SDMC_DRAM_512MB;
- default:
- g_assert_not_reached();
- break;
- }
-}
-
-static int ast2500_rambits(AspeedSDMCState *s)
-{
- switch (s->ram_size >> 20) {
- case 128:
- return ASPEED_SDMC_AST2500_128MB;
- case 256:
- return ASPEED_SDMC_AST2500_256MB;
- case 512:
- return ASPEED_SDMC_AST2500_512MB;
- case 1024:
- return ASPEED_SDMC_AST2500_1024MB;
- default:
- g_assert_not_reached();
- break;
- }
-}
-
-static int ast2600_rambits(AspeedSDMCState *s)
-{
- switch (s->ram_size >> 20) {
- case 256:
- return ASPEED_SDMC_AST2600_256MB;
- case 512:
- return ASPEED_SDMC_AST2600_512MB;
- case 1024:
- return ASPEED_SDMC_AST2600_1024MB;
- case 2048:
- return ASPEED_SDMC_AST2600_2048MB;
- default:
- g_assert_not_reached();
- break;
- }
-}
-
static void aspeed_sdmc_reset(DeviceState *dev)
{
AspeedSDMCState *s = ASPEED_SDMC(dev);
@@ -206,6 +168,19 @@ static void aspeed_sdmc_reset(DeviceState *dev)
/* Set ram size bit and defaults values */
s->regs[R_CONF] = asc->compute_conf(s, 0);
+
+ /*
+ * PHY status:
+ * - set phy status ok (set bit 1)
+ * - initial PVT calibration ok (clear bit 3)
+ * - runtime calibration ok (clear bit 5)
+ */
+ s->regs[0x100] = BIT(1);
+
+ /* PHY eye window: set all as passing */
+ s->regs[0x100 | (0x68 / 4)] = 0xff;
+ s->regs[0x100 | (0x7c / 4)] = 0xff;
+ s->regs[0x100 | (0x50 / 4)] = 0xfffffff;
}
static void aspeed_sdmc_get_ram_size(Object *obj, Visitor *v, const char *name,
@@ -298,10 +273,32 @@ static const TypeInfo aspeed_sdmc_info = {
.abstract = true,
};
+static int aspeed_sdmc_get_ram_bits(AspeedSDMCState *s)
+{
+ AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
+ int i;
+
+ /*
+ * The bitfield value encoding the RAM size is the index of the
+ * possible RAM size array
+ */
+ for (i = 0; asc->valid_ram_sizes[i]; i++) {
+ if (s->ram_size == asc->valid_ram_sizes[i]) {
+ return i;
+ }
+ }
+
+ /*
+ * Invalid RAM sizes should have been excluded when setting the
+ * SoC RAM size.
+ */
+ g_assert_not_reached();
+}
+
static uint32_t aspeed_2400_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data)
{
uint32_t fixed_conf = ASPEED_SDMC_VGA_COMPAT |
- ASPEED_SDMC_DRAM_SIZE(ast2400_rambits(s));
+ ASPEED_SDMC_DRAM_SIZE(aspeed_sdmc_get_ram_bits(s));
/* Make sure readonly bits are kept */
data &= ~ASPEED_SDMC_READONLY_MASK;
@@ -359,7 +356,7 @@ static uint32_t aspeed_2500_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data)
uint32_t fixed_conf = ASPEED_SDMC_HW_VERSION(1) |
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
ASPEED_SDMC_CACHE_INITIAL_DONE |
- ASPEED_SDMC_DRAM_SIZE(ast2500_rambits(s));
+ ASPEED_SDMC_DRAM_SIZE(aspeed_sdmc_get_ram_bits(s));
/* Make sure readonly bits are kept */
data &= ~ASPEED_SDMC_AST2500_READONLY_MASK;
@@ -425,7 +422,7 @@ static uint32_t aspeed_2600_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data)
{
uint32_t fixed_conf = ASPEED_SDMC_HW_VERSION(3) |
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
- ASPEED_SDMC_DRAM_SIZE(ast2600_rambits(s));
+ ASPEED_SDMC_DRAM_SIZE(aspeed_sdmc_get_ram_bits(s));
/* Make sure readonly bits are kept (use ast2500 mask) */
data &= ~ASPEED_SDMC_AST2500_READONLY_MASK;
@@ -436,6 +433,20 @@ static uint32_t aspeed_2600_sdmc_compute_conf(AspeedSDMCState *s, uint32_t data)
static void aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg,
uint32_t data)
{
+ /* Unprotected registers */
+ switch (reg) {
+ case R_ISR:
+ case R_MCR6C:
+ case R_TEST_START_LEN:
+ case R_TEST_FAIL_DQ:
+ case R_TEST_INIT_VAL:
+ case R_DRAM_SW:
+ case R_DRAM_TIME:
+ case R_ECC_ERR_INJECT:
+ s->regs[reg] = data;
+ return;
+ }
+
if (s->regs[R_PROT] == PROT_HARDLOCKED) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked until system reset!\n",
__func__);
@@ -443,7 +454,9 @@ static void aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg,
}
if (reg != R_PROT && s->regs[R_PROT] == PROT_SOFTLOCKED) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: SDMC is locked!\n", __func__);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: SDMC is locked! (write to MCR%02x blocked)\n",
+ __func__, reg * 4);
return;
}
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
index 5f4b26fc5f..782ff192ce 100644
--- a/hw/net/ftgmac100.c
+++ b/hw/net/ftgmac100.c
@@ -481,6 +481,37 @@ static int ftgmac100_write_bd(FTGMAC100Desc *bd, dma_addr_t addr)
return 0;
}
+static int ftgmac100_insert_vlan(FTGMAC100State *s, int frame_size,
+ uint8_t vlan_tci)
+{
+ uint8_t *vlan_hdr = s->frame + (ETH_ALEN * 2);
+ uint8_t *payload = vlan_hdr + sizeof(struct vlan_header);
+
+ if (frame_size < sizeof(struct eth_header)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: frame too small for VLAN insertion : %d bytes\n",
+ __func__, frame_size);
+ s->isr |= FTGMAC100_INT_XPKT_LOST;
+ goto out;
+ }
+
+ if (frame_size + sizeof(struct vlan_header) > sizeof(s->frame)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: frame too big : %d bytes\n",
+ __func__, frame_size);
+ s->isr |= FTGMAC100_INT_XPKT_LOST;
+ frame_size -= sizeof(struct vlan_header);
+ }
+
+ memmove(payload, vlan_hdr, frame_size - (ETH_ALEN * 2));
+ stw_be_p(vlan_hdr, ETH_P_VLAN);
+ stw_be_p(vlan_hdr + 2, vlan_tci);
+ frame_size += sizeof(struct vlan_header);
+
+out:
+ return frame_size;
+}
+
static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
uint32_t tx_descriptor)
{
@@ -507,6 +538,15 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
}
len = FTGMAC100_TXDES0_TXBUF_SIZE(bd.des0);
+ if (!len) {
+ /*
+ * 0 is an invalid size, however the HW does not raise any
+ * interrupt. Flag an error because the guest is buggy.
+ */
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid segment size\n",
+ __func__);
+ }
+
if (frame_size + len > sizeof(s->frame)) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d bytes\n",
__func__, len);
@@ -517,29 +557,21 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
if (dma_memory_read(&address_space_memory, bd.des3, ptr, len)) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to read packet @ 0x%x\n",
__func__, bd.des3);
- s->isr |= FTGMAC100_INT_NO_NPTXBUF;
+ s->isr |= FTGMAC100_INT_AHB_ERR;
break;
}
- /* Check for VLAN */
- if (bd.des0 & FTGMAC100_TXDES0_FTS &&
- bd.des1 & FTGMAC100_TXDES1_INS_VLANTAG &&
- be16_to_cpu(PKT_GET_ETH_HDR(ptr)->h_proto) != ETH_P_VLAN) {
- if (frame_size + len + 4 > sizeof(s->frame)) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d bytes\n",
- __func__, len);
- s->isr |= FTGMAC100_INT_XPKT_LOST;
- len = sizeof(s->frame) - frame_size - 4;
- }
- memmove(ptr + 16, ptr + 12, len - 12);
- stw_be_p(ptr + 12, ETH_P_VLAN);
- stw_be_p(ptr + 14, bd.des1);
- len += 4;
- }
-
ptr += len;
frame_size += len;
if (bd.des0 & FTGMAC100_TXDES0_LTS) {
+
+ /* Check for VLAN */
+ if (flags & FTGMAC100_TXDES1_INS_VLANTAG &&
+ be16_to_cpu(PKT_GET_ETH_HDR(s->frame)->h_proto) != ETH_P_VLAN) {
+ frame_size = ftgmac100_insert_vlan(s, frame_size,
+ FTGMAC100_TXDES1_VLANTAG_CI(flags));
+ }
+
if (flags & FTGMAC100_TXDES1_IP_CHKSUM) {
net_checksum_calculate(s->frame, frame_size);
}
@@ -547,9 +579,7 @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size);
ptr = s->frame;
frame_size = 0;
- if (flags & FTGMAC100_TXDES1_TXIC) {
- s->isr |= FTGMAC100_INT_XPKT_ETH;
- }
+ s->isr |= FTGMAC100_INT_XPKT_ETH;
}
if (flags & FTGMAC100_TXDES1_TX2FIC) {
@@ -619,10 +649,8 @@ static uint32_t ftgmac100_rxpoll(FTGMAC100State *s)
return cnt / div[speed];
}
-static void ftgmac100_reset(DeviceState *d)
+static void ftgmac100_do_reset(FTGMAC100State *s, bool sw_reset)
{
- FTGMAC100State *s = FTGMAC100(d);
-
/* Reset the FTGMAC100 */
s->isr = 0;
s->ier = 0;
@@ -641,7 +669,12 @@ static void ftgmac100_reset(DeviceState *d)
s->fear1 = 0;
s->tpafcr = 0xf1;
- s->maccr = 0;
+ if (sw_reset) {
+ s->maccr &= FTGMAC100_MACCR_GIGA_MODE | FTGMAC100_MACCR_FAST_MODE;
+ } else {
+ s->maccr = 0;
+ }
+
s->phycr = 0;
s->phydata = 0;
s->fcr = 0x400;
@@ -650,6 +683,11 @@ static void ftgmac100_reset(DeviceState *d)
phy_reset(s);
}
+static void ftgmac100_reset(DeviceState *d)
+{
+ ftgmac100_do_reset(FTGMAC100(d), false);
+}
+
static uint64_t ftgmac100_read(void *opaque, hwaddr addr, unsigned size)
{
FTGMAC100State *s = FTGMAC100(opaque);
@@ -669,6 +707,10 @@ static uint64_t ftgmac100_read(void *opaque, hwaddr addr, unsigned size)
return s->math[0];
case FTGMAC100_MATH1:
return s->math[1];
+ case FTGMAC100_RXR_BADR:
+ return s->rx_ring;
+ case FTGMAC100_NPTXR_BADR:
+ return s->tx_ring;
case FTGMAC100_ITC:
return s->itc;
case FTGMAC100_DBLAC:
@@ -790,7 +832,7 @@ static void ftgmac100_write(void *opaque, hwaddr addr,
case FTGMAC100_MACCR: /* MAC Device control */
s->maccr = value;
if (value & FTGMAC100_MACCR_SW_RST) {
- ftgmac100_reset(DEVICE(s));
+ ftgmac100_do_reset(s, true);
}
if (ftgmac100_can_receive(qemu_get_queue(s->nic))) {
@@ -948,6 +990,7 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf,
break;
}
+ s->isr |= FTGMAC100_INT_RPKT_FIFO;
addr = s->rx_descriptor;
while (size > 0) {
if (!ftgmac100_can_receive(nc)) {
@@ -999,8 +1042,6 @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf,
/* Last buffer in frame. */
bd.des0 |= flags | FTGMAC100_RXDES0_LRS;
s->isr |= FTGMAC100_INT_RPKT_BUF;
- } else {
- s->isr |= FTGMAC100_INT_RPKT_FIFO;
}
ftgmac100_write_bd(&bd, addr);
if (bd.des0 & s->rxdes0_edorr) {
diff --git a/hw/sd/aspeed_sdhci.c b/hw/sd/aspeed_sdhci.c
index 22cafce0fb..4f24b7d2f9 100644
--- a/hw/sd/aspeed_sdhci.c
+++ b/hw/sd/aspeed_sdhci.c
@@ -16,7 +16,9 @@
#include "hw/qdev-properties.h"
#define ASPEED_SDHCI_INFO 0x00
-#define ASPEED_SDHCI_INFO_RESET 0x00030000
+#define ASPEED_SDHCI_INFO_SLOT1 (1 << 17)
+#define ASPEED_SDHCI_INFO_SLOT0 (1 << 16)
+#define ASPEED_SDHCI_INFO_RESET (1 << 0)
#define ASPEED_SDHCI_DEBOUNCE 0x04
#define ASPEED_SDHCI_DEBOUNCE_RESET 0x00000005
#define ASPEED_SDHCI_BUS 0x08
@@ -67,6 +69,10 @@ static void aspeed_sdhci_write(void *opaque, hwaddr addr, uint64_t val,
AspeedSDHCIState *sdhci = opaque;
switch (addr) {
+ case ASPEED_SDHCI_INFO:
+ /* The RESET bit automatically clears. */
+ sdhci->regs[TO_REG(addr)] = (uint32_t)val & ~ASPEED_SDHCI_INFO_RESET;
+ break;
case ASPEED_SDHCI_SDIO_140:
sdhci->slots[0].capareg = (uint64_t)(uint32_t)val;
break;
@@ -155,7 +161,11 @@ static void aspeed_sdhci_reset(DeviceState *dev)
AspeedSDHCIState *sdhci = ASPEED_SDHCI(dev);
memset(sdhci->regs, 0, ASPEED_SDHCI_REG_SIZE);
- sdhci->regs[TO_REG(ASPEED_SDHCI_INFO)] = ASPEED_SDHCI_INFO_RESET;
+
+ sdhci->regs[TO_REG(ASPEED_SDHCI_INFO)] = ASPEED_SDHCI_INFO_SLOT0;
+ if (sdhci->num_slots == 2) {
+ sdhci->regs[TO_REG(ASPEED_SDHCI_INFO)] |= ASPEED_SDHCI_INFO_SLOT1;
+ }
sdhci->regs[TO_REG(ASPEED_SDHCI_DEBOUNCE)] = ASPEED_SDHCI_DEBOUNCE_RESET;
}
diff --git a/hw/ssi/aspeed_smc.c b/hw/ssi/aspeed_smc.c
index 4fab1f5f85..795784e5f3 100644
--- a/hw/ssi/aspeed_smc.c
+++ b/hw/ssi/aspeed_smc.c
@@ -230,7 +230,7 @@ static void aspeed_smc_reg_to_segment(const AspeedSMCState *s, uint32_t reg,
static const AspeedSegments aspeed_segments_ast2600_fmc[] = {
{ 0x0, 128 * MiB }, /* start address is readonly */
- { 0x0, 0 }, /* disabled */
+ { 128 * MiB, 128 * MiB }, /* default is disabled but needed for -kernel */
{ 0x0, 0 }, /* disabled */
};
@@ -259,7 +259,7 @@ static const AspeedSMCController controllers[] = {
.r_timings = R_TIMINGS,
.nregs_timings = 1,
.conf_enable_w0 = CONF_ENABLE_W0,
- .max_slaves = 5,
+ .max_slaves = 1,
.segments = aspeed_segments_legacy,
.flash_window_base = ASPEED_SOC_SMC_FLASH_BASE,
.flash_window_size = 0x6000000,
@@ -1299,10 +1299,8 @@ static const MemoryRegionOps aspeed_smc_ops = {
.read = aspeed_smc_read,
.write = aspeed_smc_write,
.endianness = DEVICE_LITTLE_ENDIAN,
- .valid.unaligned = true,
};
-
/*
* Initialize the custom address spaces for DMAs
*/
diff --git a/include/hw/misc/aspeed_scu.h b/include/hw/misc/aspeed_scu.h
index a6739bb846..9cd530afa2 100644
--- a/include/hw/misc/aspeed_scu.h
+++ b/include/hw/misc/aspeed_scu.h
@@ -286,6 +286,7 @@ uint32_t aspeed_scu_get_apb_freq(AspeedSCUState *s);
#define SCU_AST2500_HW_STRAP_ESPI_FLASH_ENABLE (0x1 << 26)
#define SCU_AST2500_HW_STRAP_ESPI_ENABLE (0x1 << 25)
#define SCU_AST2500_HW_STRAP_DDR4_ENABLE (0x1 << 24)
+#define SCU_AST2500_HW_STRAP_25HZ_CLOCK_MODE (0x1 << 23)
#define SCU_AST2500_HW_STRAP_ACPI_ENABLE (0x1 << 19)
#define SCU_AST2500_HW_STRAP_USBCKI_FREQ (0x1 << 18)
diff --git a/include/hw/misc/aspeed_sdmc.h b/include/hw/misc/aspeed_sdmc.h
index cea1e67fe3..c6226957dd 100644
--- a/include/hw/misc/aspeed_sdmc.h
+++ b/include/hw/misc/aspeed_sdmc.h
@@ -17,7 +17,18 @@
#define TYPE_ASPEED_2500_SDMC TYPE_ASPEED_SDMC "-ast2500"
#define TYPE_ASPEED_2600_SDMC TYPE_ASPEED_SDMC "-ast2600"
-#define ASPEED_SDMC_NR_REGS (0x174 >> 2)
+/*
+ * SDMC has 174 documented registers. In addition the u-boot device tree
+ * describes the following regions:
+ * - PHY status regs at offset 0x400, length 0x200
+ * - PHY setting regs at offset 0x100, length 0x300
+ *
+ * There are two sets of MRS (Mode Registers) configuration in ast2600 memory
+ * system: one is in the SDRAM MC (memory controller) which is used in run
+ * time, and the other is in the DDR-PHY IP which is used during DDR-PHY
+ * training.
+ */
+#define ASPEED_SDMC_NR_REGS (0x500 >> 2)
typedef struct AspeedSDMCState {
/*< private >*/