#include "qemu/bswap.h"
#include "qemu/module.h"
#include "qemu/units.h"
+#include "hw/boards.h"
#include "hw/qdev-core.h"
#include "hw/sysbus.h"
#include "hw/char/serial.h"
#include "sysemu/sysemu.h"
#include "hw/arm/allwinner-r40.h"
#include "hw/misc/allwinner-r40-dramc.h"
+#include "target/arm/cpu-qom.h"
+#include "target/arm/gtimer.h"
/* Memory map */
const hwaddr allwinner_r40_memmap[] = {
[AW_R40_DEV_SRAM_A2] = 0x00004000,
[AW_R40_DEV_SRAM_A3] = 0x00008000,
[AW_R40_DEV_SRAM_A4] = 0x0000b400,
+ [AW_R40_DEV_SRAMC] = 0x01c00000,
[AW_R40_DEV_EMAC] = 0x01c0b000,
[AW_R40_DEV_MMC0] = 0x01c0f000,
[AW_R40_DEV_MMC1] = 0x01c10000,
[AW_R40_DEV_MMC2] = 0x01c11000,
[AW_R40_DEV_MMC3] = 0x01c12000,
+ [AW_R40_DEV_AHCI] = 0x01c18000,
+ [AW_R40_DEV_EHCI1] = 0x01c19000,
+ [AW_R40_DEV_OHCI1] = 0x01c19400,
+ [AW_R40_DEV_EHCI2] = 0x01c1c000,
+ [AW_R40_DEV_OHCI2] = 0x01c1c400,
[AW_R40_DEV_CCU] = 0x01c20000,
[AW_R40_DEV_PIT] = 0x01c20c00,
+ [AW_R40_DEV_WDT] = 0x01c20c90,
[AW_R40_DEV_UART0] = 0x01c28000,
[AW_R40_DEV_UART1] = 0x01c28400,
[AW_R40_DEV_UART2] = 0x01c28800,
static struct AwR40Unimplemented r40_unimplemented[] = {
{ "d-engine", 0x01000000, 4 * MiB },
{ "d-inter", 0x01400000, 128 * KiB },
- { "sram-c", 0x01c00000, 4 * KiB },
{ "dma", 0x01c02000, 4 * KiB },
{ "nfdc", 0x01c03000, 4 * KiB },
{ "ts", 0x01c04000, 4 * KiB },
{ "usb0-host", 0x01c14000, 4 * KiB },
{ "crypto", 0x01c15000, 4 * KiB },
{ "spi2", 0x01c17000, 4 * KiB },
- { "sata", 0x01c18000, 4 * KiB },
- { "usb1-host", 0x01c19000, 4 * KiB },
+ { "usb1-phy", 0x01c19800, 2 * KiB },
{ "sid", 0x01c1b000, 4 * KiB },
- { "usb2-host", 0x01c1c000, 4 * KiB },
+ { "usb2-phy", 0x01c1c800, 2 * KiB },
{ "cs1", 0x01c1d000, 4 * KiB },
{ "spi3", 0x01c1f000, 4 * KiB },
{ "rtc", 0x01c20400, 1 * KiB },
AW_R40_GIC_SPI_MMC2 = 34,
AW_R40_GIC_SPI_MMC3 = 35,
AW_R40_GIC_SPI_EMAC = 55,
+ AW_R40_GIC_SPI_AHCI = 56,
+ AW_R40_GIC_SPI_OHCI1 = 64,
+ AW_R40_GIC_SPI_OHCI2 = 65,
+ AW_R40_GIC_SPI_EHCI1 = 76,
+ AW_R40_GIC_SPI_EHCI2 = 78,
AW_R40_GIC_SPI_GMAC = 85,
};
object_property_add_alias(obj, "clk1-freq", OBJECT(&s->timer),
"clk1-freq");
+ object_initialize_child(obj, "wdt", &s->wdt, TYPE_AW_WDT_SUN4I);
+
object_initialize_child(obj, "ccu", &s->ccu, TYPE_AW_R40_CCU);
for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
TYPE_AW_SDHOST_SUN50I_A64);
}
+ object_initialize_child(obj, "sata", &s->sata, TYPE_ALLWINNER_AHCI);
+
+ for (size_t i = 0; i < AW_R40_NUM_USB; i++) {
+ object_initialize_child(obj, "ehci[*]", &s->ehci[i],
+ TYPE_PLATFORM_EHCI);
+ object_initialize_child(obj, "ohci[*]", &s->ohci[i],
+ TYPE_SYSBUS_OHCI);
+ }
+
object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C_SUN6I);
object_initialize_child(obj, "emac", &s->emac, TYPE_AW_EMAC);
"ram-addr");
object_property_add_alias(obj, "ram-size", OBJECT(&s->dramc),
"ram-size");
+
+ object_initialize_child(obj, "sramc", &s->sramc, TYPE_AW_SRAMC_SUN8I_R40);
}
static void allwinner_r40_realize(DeviceState *dev, Error **errp)
{
const char *r40_nic_models[] = { "gmac", "emac", NULL };
AwR40State *s = AW_R40(dev);
- unsigned i;
/* CPUs */
- for (i = 0; i < AW_R40_NUM_CPUS; i++) {
+ for (unsigned i = 0; i < AW_R40_NUM_CPUS; i++) {
/*
* Disable secondary CPUs. Guest EL3 firmware will start
* maintenance interrupt signal to the appropriate GIC PPI inputs,
* and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
*/
- for (i = 0; i < AW_R40_NUM_CPUS; i++) {
+ for (unsigned i = 0; i < AW_R40_NUM_CPUS; i++) {
DeviceState *cpudev = DEVICE(&s->cpus[i]);
int ppibase = AW_R40_GIC_NUM_SPI + i * GIC_INTERNAL + GIC_NR_SGIS;
int irq;
AW_R40_GIC_SPI_TIMER1));
/* SRAM */
+ sysbus_realize(SYS_BUS_DEVICE(&s->sramc), &error_fatal);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sramc), 0, s->memmap[AW_R40_DEV_SRAMC]);
+
memory_region_init_ram(&s->sram_a1, OBJECT(dev), "sram A1",
16 * KiB, &error_abort);
memory_region_init_ram(&s->sram_a2, OBJECT(dev), "sram A2",
sysbus_realize(SYS_BUS_DEVICE(&s->ccu), &error_fatal);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccu), 0, s->memmap[AW_R40_DEV_CCU]);
+ /* SATA / AHCI */
+ sysbus_realize(SYS_BUS_DEVICE(&s->sata), &error_fatal);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->sata), 0,
+ allwinner_r40_memmap[AW_R40_DEV_AHCI]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0,
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_AHCI));
+
+ /* USB */
+ for (size_t i = 0; i < AW_R40_NUM_USB; i++) {
+ g_autofree char *bus = g_strdup_printf("usb-bus.%zu", i);
+
+ object_property_set_bool(OBJECT(&s->ehci[i]), "companion-enable", true,
+ &error_fatal);
+ sysbus_realize(SYS_BUS_DEVICE(&s->ehci[i]), &error_fatal);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ehci[i]), 0,
+ allwinner_r40_memmap[i ? AW_R40_DEV_EHCI2
+ : AW_R40_DEV_EHCI1]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->ehci[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->gic),
+ i ? AW_R40_GIC_SPI_EHCI2
+ : AW_R40_GIC_SPI_EHCI1));
+
+ object_property_set_str(OBJECT(&s->ohci[i]), "masterbus", bus,
+ &error_fatal);
+ sysbus_realize(SYS_BUS_DEVICE(&s->ohci[i]), &error_fatal);
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ohci[i]), 0,
+ allwinner_r40_memmap[i ? AW_R40_DEV_OHCI2
+ : AW_R40_DEV_OHCI1]);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->ohci[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->gic),
+ i ? AW_R40_GIC_SPI_OHCI2
+ : AW_R40_GIC_SPI_OHCI1));
+ }
+
/* SD/MMC */
for (int i = 0; i < AW_R40_NUM_MMCS; i++) {
qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->gic),
sysbus_connect_irq(SYS_BUS_DEVICE(&s->emac), 0,
qdev_get_gpio_in(DEVICE(&s->gic), AW_R40_GIC_SPI_EMAC));
+ /* WDT */
+ sysbus_realize(SYS_BUS_DEVICE(&s->wdt), &error_fatal);
+ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->wdt), 0,
+ allwinner_r40_memmap[AW_R40_DEV_WDT], 1);
+
/* Unimplemented devices */
- for (i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) {
+ for (unsigned i = 0; i < ARRAY_SIZE(r40_unimplemented); i++) {
create_unimplemented_device(r40_unimplemented[i].device_name,
r40_unimplemented[i].base,
r40_unimplemented[i].size);