target-arm queue:
* Add Aspeed AST2600 SoC support (but no new board model yet) * aspeed/wdt: Check correct register for clock source * bcm2835: code cleanups, better logging, trace events * implement v2.0 of the Arm semihosting specification * provide new 'transaction-based' ptimer API and use it for the Arm devices that use ptimers * ARM: KVM: support more than 256 CPUs -----BEGIN PGP SIGNATURE----- iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAl2l/VYZHHBldGVyLm1h eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3uDuEACO9mAyngs6B+pWkGQa7f1V 5A4qTP0gE+62SR5b6Hkny8tA+YC//D9FG9yG2+u28Duh7REmNAoSG+7oBRbuQ0p+ A3R7cvejA3Ie0uSdSXsnbDBwAzM4cSmPK1mlathtJ/nZn/GNqtTLGnYYy7aQyZqQ IwEQcLe24dt4TPX9Te62fRQPxU8S/5DyLzW+uqoWecFIgSUcwRdxv3aYoxRlF5jM /6u+lEq/08HBgKcgWgB5pdbTJyriPZuS44IXQar2LlPL3/zOPwEYJ9eEWnlop5YU H0tTG6J6BAGwA7sXNP3OyWBUWPg6j8l83fNszVjDh1SpjwzqbyrnU69NdmiAYoRB MCBEhweo/jwb0pdHcapKbAqxBTVfVy44S9of9+FnsNJL8M2RNQ2nf7Bh1aqdzDeV XooLvdhy9OOZGp+Lf66CjMVlw92yUVzR906EvBnd0BW66Ic6mv5j4Xg3UDrFDe2e ENFXYry9Bv6l9RLzWWDAh+ynxDZ7ivDmGUYAAWzdHP6v2ZQt3lKkc/SV9oMJFtf3 ff54lu1prZzfqIgx72V7hcDaQMC1Wp7ImsGGyVuG5ST1kTWjOAg4OSqH3SvyYPcY UAu+L02I+mlgswbtkKN4wu9iIIYYE1oHTw3xSEoPrUZN9x/qWT8f7dG+CkC9Cyxs fXAkUqlc+o0Pz1ZSNsBuEw== =dKth -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20191015' into staging target-arm queue: * Add Aspeed AST2600 SoC support (but no new board model yet) * aspeed/wdt: Check correct register for clock source * bcm2835: code cleanups, better logging, trace events * implement v2.0 of the Arm semihosting specification * provide new 'transaction-based' ptimer API and use it for the Arm devices that use ptimers * ARM: KVM: support more than 256 CPUs # gpg: Signature made Tue 15 Oct 2019 18:09:42 BST # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * remotes/pmaydell/tags/pull-target-arm-20191015: (67 commits) hw/misc/bcm2835_mbox: Add trace events hw/arm/bcm2835: Add various unimplemented peripherals hw/arm/bcm2835: Rename some definitions hw/arm/bcm2835_peripherals: Name various address spaces hw/arm/bcm2835_peripherals: Improve logging hw/arm/raspi: Use the IEC binary prefix definitions aspeed/soc: Add ASPEED Video stub aspeed: add support for the Aspeed MII controller of the AST2600 aspeed: Parameterise number of MACs m25p80: Add support for w25q512jv aspeed/soc: Add AST2600 support aspeed: Introduce an object class per SoC aspeed/i2c: Add AST2600 support aspeed/i2c: Introduce an object class per SoC hw/gpio: Add in AST2600 specific implementation aspeed/smc: Add AST2600 support aspeed/smc: Introduce segment operations hw: wdt_aspeed: Add AST2600 support watchdog/aspeed: Introduce an object class per SoC aspeed/sdmc: Add AST2600 support ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
69b81893bc
|
@ -41,7 +41,7 @@ obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
|
|||
obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
|
||||
obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
|
||||
obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o
|
||||
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
|
||||
obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o aspeed_ast2600.o
|
||||
obj-$(CONFIG_MPS2) += mps2.o
|
||||
obj-$(CONFIG_MPS2) += mps2-tz.o
|
||||
obj-$(CONFIG_MSF2) += msf2-soc.o
|
||||
|
|
|
@ -170,6 +170,7 @@ static void aspeed_board_init(MachineState *machine,
|
|||
AspeedSoCClass *sc;
|
||||
DriveInfo *drive0 = drive_get(IF_MTD, 0, 0);
|
||||
ram_addr_t max_ram_size;
|
||||
int i;
|
||||
|
||||
bmc = g_new0(AspeedBoardState, 1);
|
||||
|
||||
|
@ -214,7 +215,7 @@ static void aspeed_board_init(MachineState *machine,
|
|||
memory_region_allocate_system_memory(&bmc->ram, NULL, "ram", ram_size);
|
||||
memory_region_add_subregion(&bmc->ram_container, 0, &bmc->ram);
|
||||
memory_region_add_subregion(get_system_memory(),
|
||||
sc->info->memmap[ASPEED_SDRAM],
|
||||
sc->memmap[ASPEED_SDRAM],
|
||||
&bmc->ram_container);
|
||||
|
||||
max_ram_size = object_property_get_uint(OBJECT(&bmc->soc), "max-ram-size",
|
||||
|
@ -245,13 +246,26 @@ static void aspeed_board_init(MachineState *machine,
|
|||
}
|
||||
|
||||
aspeed_board_binfo.ram_size = ram_size;
|
||||
aspeed_board_binfo.loader_start = sc->info->memmap[ASPEED_SDRAM];
|
||||
aspeed_board_binfo.loader_start = sc->memmap[ASPEED_SDRAM];
|
||||
aspeed_board_binfo.nb_cpus = bmc->soc.num_cpus;
|
||||
|
||||
if (cfg->i2c_init) {
|
||||
cfg->i2c_init(bmc);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bmc->soc.sdhci.slots); i++) {
|
||||
SDHCIState *sdhci = &bmc->soc.sdhci.slots[i];
|
||||
DriveInfo *dinfo = drive_get_next(IF_SD);
|
||||
BlockBackend *blk;
|
||||
DeviceState *card;
|
||||
|
||||
blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL;
|
||||
card = qdev_create(qdev_get_child_bus(DEVICE(sdhci), "sd-bus"),
|
||||
TYPE_SD_CARD);
|
||||
qdev_prop_set_drive(card, "drive", blk, &error_fatal);
|
||||
object_property_set_bool(OBJECT(card), true, "realized", &error_fatal);
|
||||
}
|
||||
|
||||
arm_load_kernel(ARM_CPU(first_cpu), machine, &aspeed_board_binfo);
|
||||
}
|
||||
|
||||
|
@ -373,7 +387,6 @@ static void aspeed_machine_class_init(ObjectClass *oc, void *data)
|
|||
mc->desc = board->desc;
|
||||
mc->init = aspeed_machine_init;
|
||||
mc->max_cpus = ASPEED_CPUS_NUM;
|
||||
mc->no_sdcard = 1;
|
||||
mc->no_floppy = 1;
|
||||
mc->no_cdrom = 1;
|
||||
mc->no_parallel = 1;
|
||||
|
|
523
hw/arm/aspeed_ast2600.c
Normal file
523
hw/arm/aspeed_ast2600.c
Normal file
|
@ -0,0 +1,523 @@
|
|||
/*
|
||||
* ASPEED SoC 2600 family
|
||||
*
|
||||
* Copyright (c) 2016-2019, IBM Corporation.
|
||||
*
|
||||
* This code is licensed under the GPL version 2 or later. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/misc/unimp.h"
|
||||
#include "hw/arm/aspeed_soc.h"
|
||||
#include "hw/char/serial.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/i2c/aspeed_i2c.h"
|
||||
#include "net/net.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
#define ASPEED_SOC_IOMEM_SIZE 0x00200000
|
||||
|
||||
static const hwaddr aspeed_soc_ast2600_memmap[] = {
|
||||
[ASPEED_SRAM] = 0x10000000,
|
||||
/* 0x16000000 0x17FFFFFF : AHB BUS do LPC Bus bridge */
|
||||
[ASPEED_IOMEM] = 0x1E600000,
|
||||
[ASPEED_PWM] = 0x1E610000,
|
||||
[ASPEED_FMC] = 0x1E620000,
|
||||
[ASPEED_SPI1] = 0x1E630000,
|
||||
[ASPEED_SPI2] = 0x1E641000,
|
||||
[ASPEED_MII1] = 0x1E650000,
|
||||
[ASPEED_MII2] = 0x1E650008,
|
||||
[ASPEED_MII3] = 0x1E650010,
|
||||
[ASPEED_MII4] = 0x1E650018,
|
||||
[ASPEED_ETH1] = 0x1E660000,
|
||||
[ASPEED_ETH3] = 0x1E670000,
|
||||
[ASPEED_ETH2] = 0x1E680000,
|
||||
[ASPEED_ETH4] = 0x1E690000,
|
||||
[ASPEED_VIC] = 0x1E6C0000,
|
||||
[ASPEED_SDMC] = 0x1E6E0000,
|
||||
[ASPEED_SCU] = 0x1E6E2000,
|
||||
[ASPEED_XDMA] = 0x1E6E7000,
|
||||
[ASPEED_ADC] = 0x1E6E9000,
|
||||
[ASPEED_VIDEO] = 0x1E700000,
|
||||
[ASPEED_SDHCI] = 0x1E740000,
|
||||
[ASPEED_GPIO] = 0x1E780000,
|
||||
[ASPEED_GPIO_1_8V] = 0x1E780800,
|
||||
[ASPEED_RTC] = 0x1E781000,
|
||||
[ASPEED_TIMER1] = 0x1E782000,
|
||||
[ASPEED_WDT] = 0x1E785000,
|
||||
[ASPEED_LPC] = 0x1E789000,
|
||||
[ASPEED_IBT] = 0x1E789140,
|
||||
[ASPEED_I2C] = 0x1E78A000,
|
||||
[ASPEED_UART1] = 0x1E783000,
|
||||
[ASPEED_UART5] = 0x1E784000,
|
||||
[ASPEED_VUART] = 0x1E787000,
|
||||
[ASPEED_SDRAM] = 0x80000000,
|
||||
};
|
||||
|
||||
#define ASPEED_A7MPCORE_ADDR 0x40460000
|
||||
|
||||
#define ASPEED_SOC_AST2600_MAX_IRQ 128
|
||||
|
||||
static const int aspeed_soc_ast2600_irqmap[] = {
|
||||
[ASPEED_UART1] = 47,
|
||||
[ASPEED_UART2] = 48,
|
||||
[ASPEED_UART3] = 49,
|
||||
[ASPEED_UART4] = 50,
|
||||
[ASPEED_UART5] = 8,
|
||||
[ASPEED_VUART] = 8,
|
||||
[ASPEED_FMC] = 39,
|
||||
[ASPEED_SDMC] = 0,
|
||||
[ASPEED_SCU] = 12,
|
||||
[ASPEED_ADC] = 78,
|
||||
[ASPEED_XDMA] = 6,
|
||||
[ASPEED_SDHCI] = 43,
|
||||
[ASPEED_GPIO] = 40,
|
||||
[ASPEED_GPIO_1_8V] = 11,
|
||||
[ASPEED_RTC] = 13,
|
||||
[ASPEED_TIMER1] = 16,
|
||||
[ASPEED_TIMER2] = 17,
|
||||
[ASPEED_TIMER3] = 18,
|
||||
[ASPEED_TIMER4] = 19,
|
||||
[ASPEED_TIMER5] = 20,
|
||||
[ASPEED_TIMER6] = 21,
|
||||
[ASPEED_TIMER7] = 22,
|
||||
[ASPEED_TIMER8] = 23,
|
||||
[ASPEED_WDT] = 24,
|
||||
[ASPEED_PWM] = 44,
|
||||
[ASPEED_LPC] = 35,
|
||||
[ASPEED_IBT] = 35, /* LPC */
|
||||
[ASPEED_I2C] = 110, /* 110 -> 125 */
|
||||
[ASPEED_ETH1] = 2,
|
||||
[ASPEED_ETH2] = 3,
|
||||
[ASPEED_ETH3] = 32,
|
||||
[ASPEED_ETH4] = 33,
|
||||
|
||||
};
|
||||
|
||||
static qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int ctrl)
|
||||
{
|
||||
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
|
||||
|
||||
return qdev_get_gpio_in(DEVICE(&s->a7mpcore), sc->irqmap[ctrl]);
|
||||
}
|
||||
|
||||
static void aspeed_soc_ast2600_init(Object *obj)
|
||||
{
|
||||
AspeedSoCState *s = ASPEED_SOC(obj);
|
||||
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
|
||||
int i;
|
||||
char socname[8];
|
||||
char typename[64];
|
||||
|
||||
if (sscanf(sc->name, "%7s", socname) != 1) {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
for (i = 0; i < sc->num_cpus; i++) {
|
||||
object_initialize_child(obj, "cpu[*]", OBJECT(&s->cpu[i]),
|
||||
sizeof(s->cpu[i]), sc->cpu_type,
|
||||
&error_abort, NULL);
|
||||
}
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.scu-%s", socname);
|
||||
sysbus_init_child_obj(obj, "scu", OBJECT(&s->scu), sizeof(s->scu),
|
||||
typename);
|
||||
qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
|
||||
sc->silicon_rev);
|
||||
object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu),
|
||||
"hw-strap1", &error_abort);
|
||||
object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
|
||||
"hw-strap2", &error_abort);
|
||||
object_property_add_alias(obj, "hw-prot-key", OBJECT(&s->scu),
|
||||
"hw-prot-key", &error_abort);
|
||||
|
||||
sysbus_init_child_obj(obj, "a7mpcore", &s->a7mpcore,
|
||||
sizeof(s->a7mpcore), TYPE_A15MPCORE_PRIV);
|
||||
|
||||
sysbus_init_child_obj(obj, "rtc", OBJECT(&s->rtc), sizeof(s->rtc),
|
||||
TYPE_ASPEED_RTC);
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.timer-%s", socname);
|
||||
sysbus_init_child_obj(obj, "timerctrl", OBJECT(&s->timerctrl),
|
||||
sizeof(s->timerctrl), typename);
|
||||
object_property_add_const_link(OBJECT(&s->timerctrl), "scu",
|
||||
OBJECT(&s->scu), &error_abort);
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.i2c-%s", socname);
|
||||
sysbus_init_child_obj(obj, "i2c", OBJECT(&s->i2c), sizeof(s->i2c),
|
||||
typename);
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.fmc-%s", socname);
|
||||
sysbus_init_child_obj(obj, "fmc", OBJECT(&s->fmc), sizeof(s->fmc),
|
||||
typename);
|
||||
object_property_add_alias(obj, "num-cs", OBJECT(&s->fmc), "num-cs",
|
||||
&error_abort);
|
||||
object_property_add_alias(obj, "dram", OBJECT(&s->fmc), "dram",
|
||||
&error_abort);
|
||||
|
||||
for (i = 0; i < sc->spis_num; i++) {
|
||||
snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i + 1, socname);
|
||||
sysbus_init_child_obj(obj, "spi[*]", OBJECT(&s->spi[i]),
|
||||
sizeof(s->spi[i]), typename);
|
||||
}
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.sdmc-%s", socname);
|
||||
sysbus_init_child_obj(obj, "sdmc", OBJECT(&s->sdmc), sizeof(s->sdmc),
|
||||
typename);
|
||||
object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
|
||||
"ram-size", &error_abort);
|
||||
object_property_add_alias(obj, "max-ram-size", OBJECT(&s->sdmc),
|
||||
"max-ram-size", &error_abort);
|
||||
|
||||
for (i = 0; i < sc->wdts_num; i++) {
|
||||
snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname);
|
||||
sysbus_init_child_obj(obj, "wdt[*]", OBJECT(&s->wdt[i]),
|
||||
sizeof(s->wdt[i]), typename);
|
||||
object_property_add_const_link(OBJECT(&s->wdt[i]), "scu",
|
||||
OBJECT(&s->scu), &error_abort);
|
||||
}
|
||||
|
||||
for (i = 0; i < sc->macs_num; i++) {
|
||||
sysbus_init_child_obj(obj, "ftgmac100[*]", OBJECT(&s->ftgmac100[i]),
|
||||
sizeof(s->ftgmac100[i]), TYPE_FTGMAC100);
|
||||
|
||||
sysbus_init_child_obj(obj, "mii[*]", &s->mii[i], sizeof(s->mii[i]),
|
||||
TYPE_ASPEED_MII);
|
||||
object_property_add_const_link(OBJECT(&s->mii[i]), "nic",
|
||||
OBJECT(&s->ftgmac100[i]),
|
||||
&error_abort);
|
||||
}
|
||||
|
||||
sysbus_init_child_obj(obj, "xdma", OBJECT(&s->xdma), sizeof(s->xdma),
|
||||
TYPE_ASPEED_XDMA);
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname);
|
||||
sysbus_init_child_obj(obj, "gpio", OBJECT(&s->gpio), sizeof(s->gpio),
|
||||
typename);
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.gpio-%s-1_8v", socname);
|
||||
sysbus_init_child_obj(obj, "gpio_1_8v", OBJECT(&s->gpio_1_8v),
|
||||
sizeof(s->gpio_1_8v), typename);
|
||||
|
||||
sysbus_init_child_obj(obj, "sdc", OBJECT(&s->sdhci), sizeof(s->sdhci),
|
||||
TYPE_ASPEED_SDHCI);
|
||||
|
||||
/* Init sd card slot class here so that they're under the correct parent */
|
||||
for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
|
||||
sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(&s->sdhci.slots[i]),
|
||||
sizeof(s->sdhci.slots[i]), TYPE_SYSBUS_SDHCI);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* ASPEED ast2600 has 0xf as cluster ID
|
||||
*
|
||||
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0388e/CIHEBGFG.html
|
||||
*/
|
||||
static uint64_t aspeed_calc_affinity(int cpu)
|
||||
{
|
||||
return (0xf << ARM_AFF1_SHIFT) | cpu;
|
||||
}
|
||||
|
||||
static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
int i;
|
||||
AspeedSoCState *s = ASPEED_SOC(dev);
|
||||
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
|
||||
Error *err = NULL, *local_err = NULL;
|
||||
qemu_irq irq;
|
||||
|
||||
/* IO space */
|
||||
create_unimplemented_device("aspeed_soc.io", sc->memmap[ASPEED_IOMEM],
|
||||
ASPEED_SOC_IOMEM_SIZE);
|
||||
|
||||
/* Video engine stub */
|
||||
create_unimplemented_device("aspeed.video", sc->memmap[ASPEED_VIDEO],
|
||||
0x1000);
|
||||
|
||||
if (s->num_cpus > sc->num_cpus) {
|
||||
warn_report("%s: invalid number of CPUs %d, using default %d",
|
||||
sc->name, s->num_cpus, sc->num_cpus);
|
||||
s->num_cpus = sc->num_cpus;
|
||||
}
|
||||
|
||||
/* CPU */
|
||||
for (i = 0; i < s->num_cpus; i++) {
|
||||
object_property_set_int(OBJECT(&s->cpu[i]), QEMU_PSCI_CONDUIT_SMC,
|
||||
"psci-conduit", &error_abort);
|
||||
if (s->num_cpus > 1) {
|
||||
object_property_set_int(OBJECT(&s->cpu[i]),
|
||||
ASPEED_A7MPCORE_ADDR,
|
||||
"reset-cbar", &error_abort);
|
||||
}
|
||||
object_property_set_int(OBJECT(&s->cpu[i]), aspeed_calc_affinity(i),
|
||||
"mp-affinity", &error_abort);
|
||||
|
||||
/*
|
||||
* TODO: the secondary CPUs are started and a boot helper
|
||||
* is needed when using -kernel
|
||||
*/
|
||||
|
||||
object_property_set_bool(OBJECT(&s->cpu[i]), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* A7MPCORE */
|
||||
object_property_set_int(OBJECT(&s->a7mpcore), s->num_cpus, "num-cpu",
|
||||
&error_abort);
|
||||
object_property_set_int(OBJECT(&s->a7mpcore),
|
||||
ASPEED_SOC_AST2600_MAX_IRQ + GIC_INTERNAL,
|
||||
"num-irq", &error_abort);
|
||||
|
||||
object_property_set_bool(OBJECT(&s->a7mpcore), true, "realized",
|
||||
&error_abort);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->a7mpcore), 0, ASPEED_A7MPCORE_ADDR);
|
||||
|
||||
for (i = 0; i < s->num_cpus; i++) {
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(&s->a7mpcore);
|
||||
DeviceState *d = DEVICE(qemu_get_cpu(i));
|
||||
|
||||
irq = qdev_get_gpio_in(d, ARM_CPU_IRQ);
|
||||
sysbus_connect_irq(sbd, i, irq);
|
||||
irq = qdev_get_gpio_in(d, ARM_CPU_FIQ);
|
||||
sysbus_connect_irq(sbd, i + s->num_cpus, irq);
|
||||
irq = qdev_get_gpio_in(d, ARM_CPU_VIRQ);
|
||||
sysbus_connect_irq(sbd, i + 2 * s->num_cpus, irq);
|
||||
irq = qdev_get_gpio_in(d, ARM_CPU_VFIQ);
|
||||
sysbus_connect_irq(sbd, i + 3 * s->num_cpus, irq);
|
||||
}
|
||||
|
||||
/* SRAM */
|
||||
memory_region_init_ram(&s->sram, OBJECT(dev), "aspeed.sram",
|
||||
sc->sram_size, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
memory_region_add_subregion(get_system_memory(),
|
||||
sc->memmap[ASPEED_SRAM], &s->sram);
|
||||
|
||||
/* SCU */
|
||||
object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_SCU]);
|
||||
|
||||
/* RTC */
|
||||
object_property_set_bool(OBJECT(&s->rtc), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, sc->memmap[ASPEED_RTC]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_RTC));
|
||||
|
||||
/* Timer */
|
||||
object_property_set_bool(OBJECT(&s->timerctrl), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->timerctrl), 0,
|
||||
sc->memmap[ASPEED_TIMER1]);
|
||||
for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
|
||||
qemu_irq irq = aspeed_soc_get_irq(s, ASPEED_TIMER1 + i);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
|
||||
}
|
||||
|
||||
/* UART - attach an 8250 to the IO space as our UART5 */
|
||||
if (serial_hd(0)) {
|
||||
qemu_irq uart5 = aspeed_soc_get_irq(s, ASPEED_UART5);
|
||||
serial_mm_init(get_system_memory(), sc->memmap[ASPEED_UART5], 2,
|
||||
uart5, 38400, serial_hd(0), DEVICE_LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
/* I2C */
|
||||
object_property_set_bool(OBJECT(&s->i2c), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, sc->memmap[ASPEED_I2C]);
|
||||
for (i = 0; i < ASPEED_I2C_GET_CLASS(&s->i2c)->num_busses; i++) {
|
||||
qemu_irq irq = qdev_get_gpio_in(DEVICE(&s->a7mpcore),
|
||||
sc->irqmap[ASPEED_I2C] + i);
|
||||
/*
|
||||
* The AST2600 SoC has one IRQ per I2C bus. Skip the common
|
||||
* IRQ (AST2400 and AST2500) and connect all bussses.
|
||||
*/
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), i + 1, irq);
|
||||
}
|
||||
|
||||
/* FMC, The number of CS is set at the board level */
|
||||
object_property_set_int(OBJECT(&s->fmc), sc->memmap[ASPEED_SDRAM],
|
||||
"sdram-base", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
object_property_set_bool(OBJECT(&s->fmc), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 0, sc->memmap[ASPEED_FMC]);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 1,
|
||||
s->fmc.ctrl->flash_window_base);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_FMC));
|
||||
|
||||
/* SPI */
|
||||
for (i = 0; i < sc->spis_num; i++) {
|
||||
object_property_set_int(OBJECT(&s->spi[i]), 1, "num-cs", &err);
|
||||
object_property_set_bool(OBJECT(&s->spi[i]), true, "realized",
|
||||
&local_err);
|
||||
error_propagate(&err, local_err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0,
|
||||
sc->memmap[ASPEED_SPI1 + i]);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 1,
|
||||
s->spi[i].ctrl->flash_window_base);
|
||||
}
|
||||
|
||||
/* SDMC - SDRAM Memory Controller */
|
||||
object_property_set_bool(OBJECT(&s->sdmc), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, sc->memmap[ASPEED_SDMC]);
|
||||
|
||||
/* Watch dog */
|
||||
for (i = 0; i < sc->wdts_num; i++) {
|
||||
AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]);
|
||||
|
||||
object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0,
|
||||
sc->memmap[ASPEED_WDT] + i * awc->offset);
|
||||
}
|
||||
|
||||
/* Net */
|
||||
for (i = 0; i < nb_nics && i < sc->macs_num; i++) {
|
||||
qdev_set_nic_properties(DEVICE(&s->ftgmac100[i]), &nd_table[i]);
|
||||
object_property_set_bool(OBJECT(&s->ftgmac100[i]), true, "aspeed",
|
||||
&err);
|
||||
object_property_set_bool(OBJECT(&s->ftgmac100[i]), true, "realized",
|
||||
&local_err);
|
||||
error_propagate(&err, local_err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
|
||||
sc->memmap[ASPEED_ETH1 + i]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_ETH1 + i));
|
||||
|
||||
object_property_set_bool(OBJECT(&s->mii[i]), true, "realized",
|
||||
&err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->mii[i]), 0,
|
||||
sc->memmap[ASPEED_MII1 + i]);
|
||||
}
|
||||
|
||||
/* XDMA */
|
||||
object_property_set_bool(OBJECT(&s->xdma), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->xdma), 0,
|
||||
sc->memmap[ASPEED_XDMA]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->xdma), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_XDMA));
|
||||
|
||||
/* GPIO */
|
||||
object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, sc->memmap[ASPEED_GPIO]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_GPIO));
|
||||
|
||||
object_property_set_bool(OBJECT(&s->gpio_1_8v), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio_1_8v), 0,
|
||||
sc->memmap[ASPEED_GPIO_1_8V]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio_1_8v), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_GPIO_1_8V));
|
||||
|
||||
/* SDHCI */
|
||||
object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci), 0,
|
||||
sc->memmap[ASPEED_SDHCI]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_SDHCI));
|
||||
}
|
||||
|
||||
static void aspeed_soc_ast2600_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc);
|
||||
|
||||
dc->realize = aspeed_soc_ast2600_realize;
|
||||
|
||||
sc->name = "ast2600-a0";
|
||||
sc->cpu_type = ARM_CPU_TYPE_NAME("cortex-a7");
|
||||
sc->silicon_rev = AST2600_A0_SILICON_REV;
|
||||
sc->sram_size = 0x10000;
|
||||
sc->spis_num = 2;
|
||||
sc->wdts_num = 4;
|
||||
sc->macs_num = 4;
|
||||
sc->irqmap = aspeed_soc_ast2600_irqmap;
|
||||
sc->memmap = aspeed_soc_ast2600_memmap;
|
||||
sc->num_cpus = 2;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_soc_ast2600_type_info = {
|
||||
.name = "ast2600-a0",
|
||||
.parent = TYPE_ASPEED_SOC,
|
||||
.instance_size = sizeof(AspeedSoCState),
|
||||
.instance_init = aspeed_soc_ast2600_init,
|
||||
.class_init = aspeed_soc_ast2600_class_init,
|
||||
.class_size = sizeof(AspeedSoCClass),
|
||||
};
|
||||
|
||||
static void aspeed_soc_register_types(void)
|
||||
{
|
||||
type_register_static(&aspeed_soc_ast2600_type_info);
|
||||
};
|
||||
|
||||
type_init(aspeed_soc_register_types)
|
|
@ -34,8 +34,10 @@ static const hwaddr aspeed_soc_ast2400_memmap[] = {
|
|||
[ASPEED_SDMC] = 0x1E6E0000,
|
||||
[ASPEED_SCU] = 0x1E6E2000,
|
||||
[ASPEED_XDMA] = 0x1E6E7000,
|
||||
[ASPEED_VIDEO] = 0x1E700000,
|
||||
[ASPEED_ADC] = 0x1E6E9000,
|
||||
[ASPEED_SRAM] = 0x1E720000,
|
||||
[ASPEED_SDHCI] = 0x1E740000,
|
||||
[ASPEED_GPIO] = 0x1E780000,
|
||||
[ASPEED_RTC] = 0x1E781000,
|
||||
[ASPEED_TIMER1] = 0x1E782000,
|
||||
|
@ -62,7 +64,9 @@ static const hwaddr aspeed_soc_ast2500_memmap[] = {
|
|||
[ASPEED_SCU] = 0x1E6E2000,
|
||||
[ASPEED_XDMA] = 0x1E6E7000,
|
||||
[ASPEED_ADC] = 0x1E6E9000,
|
||||
[ASPEED_VIDEO] = 0x1E700000,
|
||||
[ASPEED_SRAM] = 0x1E720000,
|
||||
[ASPEED_SDHCI] = 0x1E740000,
|
||||
[ASPEED_GPIO] = 0x1E780000,
|
||||
[ASPEED_RTC] = 0x1E781000,
|
||||
[ASPEED_TIMER1] = 0x1E782000,
|
||||
|
@ -108,39 +112,16 @@ static const int aspeed_soc_ast2400_irqmap[] = {
|
|||
[ASPEED_ETH1] = 2,
|
||||
[ASPEED_ETH2] = 3,
|
||||
[ASPEED_XDMA] = 6,
|
||||
[ASPEED_SDHCI] = 26,
|
||||
};
|
||||
|
||||
#define aspeed_soc_ast2500_irqmap aspeed_soc_ast2400_irqmap
|
||||
|
||||
static const AspeedSoCInfo aspeed_socs[] = {
|
||||
{
|
||||
.name = "ast2400-a1",
|
||||
.cpu_type = ARM_CPU_TYPE_NAME("arm926"),
|
||||
.silicon_rev = AST2400_A1_SILICON_REV,
|
||||
.sram_size = 0x8000,
|
||||
.spis_num = 1,
|
||||
.wdts_num = 2,
|
||||
.irqmap = aspeed_soc_ast2400_irqmap,
|
||||
.memmap = aspeed_soc_ast2400_memmap,
|
||||
.num_cpus = 1,
|
||||
}, {
|
||||
.name = "ast2500-a1",
|
||||
.cpu_type = ARM_CPU_TYPE_NAME("arm1176"),
|
||||
.silicon_rev = AST2500_A1_SILICON_REV,
|
||||
.sram_size = 0x9000,
|
||||
.spis_num = 2,
|
||||
.wdts_num = 3,
|
||||
.irqmap = aspeed_soc_ast2500_irqmap,
|
||||
.memmap = aspeed_soc_ast2500_memmap,
|
||||
.num_cpus = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static qemu_irq aspeed_soc_get_irq(AspeedSoCState *s, int ctrl)
|
||||
{
|
||||
AspeedSoCClass *sc = ASPEED_SOC_GET_CLASS(s);
|
||||
|
||||
return qdev_get_gpio_in(DEVICE(&s->vic), sc->info->irqmap[ctrl]);
|
||||
return qdev_get_gpio_in(DEVICE(&s->vic), sc->irqmap[ctrl]);
|
||||
}
|
||||
|
||||
static void aspeed_soc_init(Object *obj)
|
||||
|
@ -151,13 +132,13 @@ static void aspeed_soc_init(Object *obj)
|
|||
char socname[8];
|
||||
char typename[64];
|
||||
|
||||
if (sscanf(sc->info->name, "%7s", socname) != 1) {
|
||||
if (sscanf(sc->name, "%7s", socname) != 1) {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
for (i = 0; i < sc->info->num_cpus; i++) {
|
||||
for (i = 0; i < sc->num_cpus; i++) {
|
||||
object_initialize_child(obj, "cpu[*]", OBJECT(&s->cpu[i]),
|
||||
sizeof(s->cpu[i]), sc->info->cpu_type,
|
||||
sizeof(s->cpu[i]), sc->cpu_type,
|
||||
&error_abort, NULL);
|
||||
}
|
||||
|
||||
|
@ -165,7 +146,7 @@ static void aspeed_soc_init(Object *obj)
|
|||
sysbus_init_child_obj(obj, "scu", OBJECT(&s->scu), sizeof(s->scu),
|
||||
typename);
|
||||
qdev_prop_set_uint32(DEVICE(&s->scu), "silicon-rev",
|
||||
sc->info->silicon_rev);
|
||||
sc->silicon_rev);
|
||||
object_property_add_alias(obj, "hw-strap1", OBJECT(&s->scu),
|
||||
"hw-strap1", &error_abort);
|
||||
object_property_add_alias(obj, "hw-strap2", OBJECT(&s->scu),
|
||||
|
@ -179,13 +160,15 @@ static void aspeed_soc_init(Object *obj)
|
|||
sysbus_init_child_obj(obj, "rtc", OBJECT(&s->rtc), sizeof(s->rtc),
|
||||
TYPE_ASPEED_RTC);
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.timer-%s", socname);
|
||||
sysbus_init_child_obj(obj, "timerctrl", OBJECT(&s->timerctrl),
|
||||
sizeof(s->timerctrl), TYPE_ASPEED_TIMER);
|
||||
sizeof(s->timerctrl), typename);
|
||||
object_property_add_const_link(OBJECT(&s->timerctrl), "scu",
|
||||
OBJECT(&s->scu), &error_abort);
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.i2c-%s", socname);
|
||||
sysbus_init_child_obj(obj, "i2c", OBJECT(&s->i2c), sizeof(s->i2c),
|
||||
TYPE_ASPEED_I2C);
|
||||
typename);
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.fmc-%s", socname);
|
||||
sysbus_init_child_obj(obj, "fmc", OBJECT(&s->fmc), sizeof(s->fmc),
|
||||
|
@ -195,31 +178,29 @@ static void aspeed_soc_init(Object *obj)
|
|||
object_property_add_alias(obj, "dram", OBJECT(&s->fmc), "dram",
|
||||
&error_abort);
|
||||
|
||||
for (i = 0; i < sc->info->spis_num; i++) {
|
||||
for (i = 0; i < sc->spis_num; i++) {
|
||||
snprintf(typename, sizeof(typename), "aspeed.spi%d-%s", i + 1, socname);
|
||||
sysbus_init_child_obj(obj, "spi[*]", OBJECT(&s->spi[i]),
|
||||
sizeof(s->spi[i]), typename);
|
||||
}
|
||||
|
||||
snprintf(typename, sizeof(typename), "aspeed.sdmc-%s", socname);
|
||||
sysbus_init_child_obj(obj, "sdmc", OBJECT(&s->sdmc), sizeof(s->sdmc),
|
||||
TYPE_ASPEED_SDMC);
|
||||
qdev_prop_set_uint32(DEVICE(&s->sdmc), "silicon-rev",
|
||||
sc->info->silicon_rev);
|
||||
typename);
|
||||
object_property_add_alias(obj, "ram-size", OBJECT(&s->sdmc),
|
||||
"ram-size", &error_abort);
|
||||
object_property_add_alias(obj, "max-ram-size", OBJECT(&s->sdmc),
|
||||
"max-ram-size", &error_abort);
|
||||
|
||||
for (i = 0; i < sc->info->wdts_num; i++) {
|
||||
for (i = 0; i < sc->wdts_num; i++) {
|
||||
snprintf(typename, sizeof(typename), "aspeed.wdt-%s", socname);
|
||||
sysbus_init_child_obj(obj, "wdt[*]", OBJECT(&s->wdt[i]),
|
||||
sizeof(s->wdt[i]), TYPE_ASPEED_WDT);
|
||||
qdev_prop_set_uint32(DEVICE(&s->wdt[i]), "silicon-rev",
|
||||
sc->info->silicon_rev);
|
||||
sizeof(s->wdt[i]), typename);
|
||||
object_property_add_const_link(OBJECT(&s->wdt[i]), "scu",
|
||||
OBJECT(&s->scu), &error_abort);
|
||||
}
|
||||
|
||||
for (i = 0; i < ASPEED_MACS_NUM; i++) {
|
||||
for (i = 0; i < sc->macs_num; i++) {
|
||||
sysbus_init_child_obj(obj, "ftgmac100[*]", OBJECT(&s->ftgmac100[i]),
|
||||
sizeof(s->ftgmac100[i]), TYPE_FTGMAC100);
|
||||
}
|
||||
|
@ -230,6 +211,15 @@ static void aspeed_soc_init(Object *obj)
|
|||
snprintf(typename, sizeof(typename), "aspeed.gpio-%s", socname);
|
||||
sysbus_init_child_obj(obj, "gpio", OBJECT(&s->gpio), sizeof(s->gpio),
|
||||
typename);
|
||||
|
||||
sysbus_init_child_obj(obj, "sdc", OBJECT(&s->sdhci), sizeof(s->sdhci),
|
||||
TYPE_ASPEED_SDHCI);
|
||||
|
||||
/* Init sd card slot class here so that they're under the correct parent */
|
||||
for (i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
|
||||
sysbus_init_child_obj(obj, "sdhci[*]", OBJECT(&s->sdhci.slots[i]),
|
||||
sizeof(s->sdhci.slots[i]), TYPE_SYSBUS_SDHCI);
|
||||
}
|
||||
}
|
||||
|
||||
static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
||||
|
@ -240,13 +230,17 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||
Error *err = NULL, *local_err = NULL;
|
||||
|
||||
/* IO space */
|
||||
create_unimplemented_device("aspeed_soc.io", sc->info->memmap[ASPEED_IOMEM],
|
||||
create_unimplemented_device("aspeed_soc.io", sc->memmap[ASPEED_IOMEM],
|
||||
ASPEED_SOC_IOMEM_SIZE);
|
||||
|
||||
if (s->num_cpus > sc->info->num_cpus) {
|
||||
/* Video engine stub */
|
||||
create_unimplemented_device("aspeed.video", sc->memmap[ASPEED_VIDEO],
|
||||
0x1000);
|
||||
|
||||
if (s->num_cpus > sc->num_cpus) {
|
||||
warn_report("%s: invalid number of CPUs %d, using default %d",
|
||||
sc->info->name, s->num_cpus, sc->info->num_cpus);
|
||||
s->num_cpus = sc->info->num_cpus;
|
||||
sc->name, s->num_cpus, sc->num_cpus);
|
||||
s->num_cpus = sc->num_cpus;
|
||||
}
|
||||
|
||||
/* CPU */
|
||||
|
@ -260,13 +254,13 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
/* SRAM */
|
||||
memory_region_init_ram(&s->sram, OBJECT(dev), "aspeed.sram",
|
||||
sc->info->sram_size, &err);
|
||||
sc->sram_size, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
memory_region_add_subregion(get_system_memory(),
|
||||
sc->info->memmap[ASPEED_SRAM], &s->sram);
|
||||
sc->memmap[ASPEED_SRAM], &s->sram);
|
||||
|
||||
/* SCU */
|
||||
object_property_set_bool(OBJECT(&s->scu), true, "realized", &err);
|
||||
|
@ -274,7 +268,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, sc->info->memmap[ASPEED_SCU]);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->scu), 0, sc->memmap[ASPEED_SCU]);
|
||||
|
||||
/* VIC */
|
||||
object_property_set_bool(OBJECT(&s->vic), true, "realized", &err);
|
||||
|
@ -282,7 +276,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, sc->info->memmap[ASPEED_VIC]);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->vic), 0, sc->memmap[ASPEED_VIC]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 0,
|
||||
qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ));
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->vic), 1,
|
||||
|
@ -294,7 +288,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, sc->info->memmap[ASPEED_RTC]);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, sc->memmap[ASPEED_RTC]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->rtc), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_RTC));
|
||||
|
||||
|
@ -305,7 +299,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->timerctrl), 0,
|
||||
sc->info->memmap[ASPEED_TIMER1]);
|
||||
sc->memmap[ASPEED_TIMER1]);
|
||||
for (i = 0; i < ASPEED_TIMER_NR_TIMERS; i++) {
|
||||
qemu_irq irq = aspeed_soc_get_irq(s, ASPEED_TIMER1 + i);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
|
||||
|
@ -314,7 +308,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||
/* UART - attach an 8250 to the IO space as our UART5 */
|
||||
if (serial_hd(0)) {
|
||||
qemu_irq uart5 = aspeed_soc_get_irq(s, ASPEED_UART5);
|
||||
serial_mm_init(get_system_memory(), sc->info->memmap[ASPEED_UART5], 2,
|
||||
serial_mm_init(get_system_memory(), sc->memmap[ASPEED_UART5], 2,
|
||||
uart5, 38400, serial_hd(0), DEVICE_LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
|
@ -324,12 +318,12 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, sc->info->memmap[ASPEED_I2C]);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, sc->memmap[ASPEED_I2C]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_I2C));
|
||||
|
||||
/* FMC, The number of CS is set at the board level */
|
||||
object_property_set_int(OBJECT(&s->fmc), sc->info->memmap[ASPEED_SDRAM],
|
||||
object_property_set_int(OBJECT(&s->fmc), sc->memmap[ASPEED_SDRAM],
|
||||
"sdram-base", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
|
@ -340,14 +334,14 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 0, sc->info->memmap[ASPEED_FMC]);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 0, sc->memmap[ASPEED_FMC]);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 1,
|
||||
s->fmc.ctrl->flash_window_base);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_FMC));
|
||||
|
||||
/* SPI */
|
||||
for (i = 0; i < sc->info->spis_num; i++) {
|
||||
for (i = 0; i < sc->spis_num; i++) {
|
||||
object_property_set_int(OBJECT(&s->spi[i]), 1, "num-cs", &err);
|
||||
object_property_set_bool(OBJECT(&s->spi[i]), true, "realized",
|
||||
&local_err);
|
||||
|
@ -357,7 +351,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0,
|
||||
sc->info->memmap[ASPEED_SPI1 + i]);
|
||||
sc->memmap[ASPEED_SPI1 + i]);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 1,
|
||||
s->spi[i].ctrl->flash_window_base);
|
||||
}
|
||||
|
@ -368,21 +362,23 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, sc->info->memmap[ASPEED_SDMC]);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdmc), 0, sc->memmap[ASPEED_SDMC]);
|
||||
|
||||
/* Watch dog */
|
||||
for (i = 0; i < sc->info->wdts_num; i++) {
|
||||
for (i = 0; i < sc->wdts_num; i++) {
|
||||
AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(&s->wdt[i]);
|
||||
|
||||
object_property_set_bool(OBJECT(&s->wdt[i]), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->wdt[i]), 0,
|
||||
sc->info->memmap[ASPEED_WDT] + i * 0x20);
|
||||
sc->memmap[ASPEED_WDT] + i * awc->offset);
|
||||
}
|
||||
|
||||
/* Net */
|
||||
for (i = 0; i < nb_nics; i++) {
|
||||
for (i = 0; i < nb_nics && i < sc->macs_num; i++) {
|
||||
qdev_set_nic_properties(DEVICE(&s->ftgmac100[i]), &nd_table[i]);
|
||||
object_property_set_bool(OBJECT(&s->ftgmac100[i]), true, "aspeed",
|
||||
&err);
|
||||
|
@ -394,7 +390,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
|
||||
sc->info->memmap[ASPEED_ETH1 + i]);
|
||||
sc->memmap[ASPEED_ETH1 + i]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->ftgmac100[i]), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_ETH1 + i));
|
||||
}
|
||||
|
@ -406,7 +402,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->xdma), 0,
|
||||
sc->info->memmap[ASPEED_XDMA]);
|
||||
sc->memmap[ASPEED_XDMA]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->xdma), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_XDMA));
|
||||
|
||||
|
@ -416,9 +412,20 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
|
|||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, sc->info->memmap[ASPEED_GPIO]);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio), 0, sc->memmap[ASPEED_GPIO]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpio), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_GPIO));
|
||||
|
||||
/* SDHCI */
|
||||
object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci), 0,
|
||||
sc->memmap[ASPEED_SDHCI]);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
|
||||
aspeed_soc_get_irq(s, ASPEED_SDHCI));
|
||||
}
|
||||
static Property aspeed_soc_properties[] = {
|
||||
DEFINE_PROP_UINT32("num-cpus", AspeedSoCState, num_cpus, 0),
|
||||
|
@ -428,9 +435,7 @@ static Property aspeed_soc_properties[] = {
|
|||
static void aspeed_soc_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc);
|
||||
|
||||
sc->info = (AspeedSoCInfo *) data;
|
||||
dc->realize = aspeed_soc_realize;
|
||||
/* Reason: Uses serial_hds and nd_table in realize() directly */
|
||||
dc->user_creatable = false;
|
||||
|
@ -440,26 +445,64 @@ static void aspeed_soc_class_init(ObjectClass *oc, void *data)
|
|||
static const TypeInfo aspeed_soc_type_info = {
|
||||
.name = TYPE_ASPEED_SOC,
|
||||
.parent = TYPE_DEVICE,
|
||||
.instance_init = aspeed_soc_init,
|
||||
.instance_size = sizeof(AspeedSoCState),
|
||||
.class_size = sizeof(AspeedSoCClass),
|
||||
.class_init = aspeed_soc_class_init,
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void aspeed_soc_register_types(void)
|
||||
static void aspeed_soc_ast2400_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
int i;
|
||||
AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc);
|
||||
|
||||
type_register_static(&aspeed_soc_type_info);
|
||||
for (i = 0; i < ARRAY_SIZE(aspeed_socs); ++i) {
|
||||
TypeInfo ti = {
|
||||
.name = aspeed_socs[i].name,
|
||||
.parent = TYPE_ASPEED_SOC,
|
||||
.class_init = aspeed_soc_class_init,
|
||||
.class_data = (void *) &aspeed_socs[i],
|
||||
};
|
||||
type_register(&ti);
|
||||
}
|
||||
sc->name = "ast2400-a1";
|
||||
sc->cpu_type = ARM_CPU_TYPE_NAME("arm926");
|
||||
sc->silicon_rev = AST2400_A1_SILICON_REV;
|
||||
sc->sram_size = 0x8000;
|
||||
sc->spis_num = 1;
|
||||
sc->wdts_num = 2;
|
||||
sc->macs_num = 2;
|
||||
sc->irqmap = aspeed_soc_ast2400_irqmap;
|
||||
sc->memmap = aspeed_soc_ast2400_memmap;
|
||||
sc->num_cpus = 1;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_soc_ast2400_type_info = {
|
||||
.name = "ast2400-a1",
|
||||
.parent = TYPE_ASPEED_SOC,
|
||||
.instance_init = aspeed_soc_init,
|
||||
.instance_size = sizeof(AspeedSoCState),
|
||||
.class_init = aspeed_soc_ast2400_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_soc_ast2500_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
AspeedSoCClass *sc = ASPEED_SOC_CLASS(oc);
|
||||
|
||||
sc->name = "ast2500-a1";
|
||||
sc->cpu_type = ARM_CPU_TYPE_NAME("arm1176");
|
||||
sc->silicon_rev = AST2500_A1_SILICON_REV;
|
||||
sc->sram_size = 0x9000;
|
||||
sc->spis_num = 2;
|
||||
sc->wdts_num = 3;
|
||||
sc->macs_num = 2;
|
||||
sc->irqmap = aspeed_soc_ast2500_irqmap;
|
||||
sc->memmap = aspeed_soc_ast2500_memmap;
|
||||
sc->num_cpus = 1;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_soc_ast2500_type_info = {
|
||||
.name = "ast2500-a1",
|
||||
.parent = TYPE_ASPEED_SOC,
|
||||
.instance_init = aspeed_soc_init,
|
||||
.instance_size = sizeof(AspeedSoCState),
|
||||
.class_init = aspeed_soc_ast2500_class_init,
|
||||
};
|
||||
static void aspeed_soc_register_types(void)
|
||||
{
|
||||
type_register_static(&aspeed_soc_type_info);
|
||||
type_register_static(&aspeed_soc_ast2400_type_info);
|
||||
type_register_static(&aspeed_soc_ast2500_type_info);
|
||||
};
|
||||
|
||||
type_init(aspeed_soc_register_types)
|
||||
|
|
|
@ -22,6 +22,20 @@
|
|||
/* Capabilities for SD controller: no DMA, high-speed, default clocks etc. */
|
||||
#define BCM2835_SDHC_CAPAREG 0x52134b4
|
||||
|
||||
static void create_unimp(BCM2835PeripheralState *ps,
|
||||
UnimplementedDeviceState *uds,
|
||||
const char *name, hwaddr ofs, hwaddr size)
|
||||
{
|
||||
sysbus_init_child_obj(OBJECT(ps), name, uds,
|
||||
sizeof(UnimplementedDeviceState),
|
||||
TYPE_UNIMPLEMENTED_DEVICE);
|
||||
qdev_prop_set_string(DEVICE(uds), "name", name);
|
||||
qdev_prop_set_uint64(DEVICE(uds), "size", size);
|
||||
object_property_set_bool(OBJECT(uds), true, "realized", &error_fatal);
|
||||
memory_region_add_subregion_overlap(&ps->peri_mr, ofs,
|
||||
sysbus_mmio_get_region(SYS_BUS_DEVICE(uds), 0), -1000);
|
||||
}
|
||||
|
||||
static void bcm2835_peripherals_init(Object *obj)
|
||||
{
|
||||
BCM2835PeripheralState *s = BCM2835_PERIPHERALS(obj);
|
||||
|
@ -165,7 +179,8 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
|
|||
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->uart0), 0));
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart0), 0,
|
||||
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
|
||||
INTERRUPT_UART));
|
||||
INTERRUPT_UART0));
|
||||
|
||||
/* AUX / UART1 */
|
||||
qdev_prop_set_chr(DEVICE(&s->aux), "chardev", serial_hd(1));
|
||||
|
||||
|
@ -175,7 +190,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
|
|||
return;
|
||||
}
|
||||
|
||||
memory_region_add_subregion(&s->peri_mr, UART1_OFFSET,
|
||||
memory_region_add_subregion(&s->peri_mr, AUX_OFFSET,
|
||||
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->aux), 0));
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->aux), 0,
|
||||
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
|
||||
|
@ -268,7 +283,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
|
|||
return;
|
||||
}
|
||||
|
||||
memory_region_add_subregion(&s->peri_mr, EMMC_OFFSET,
|
||||
memory_region_add_subregion(&s->peri_mr, EMMC1_OFFSET,
|
||||
sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhci), 0));
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0,
|
||||
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
|
||||
|
@ -322,6 +337,23 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
|
|||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
|
||||
create_unimp(s, &s->systmr, "bcm2835-systimer", ST_OFFSET, 0x20);
|
||||
create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000);
|
||||
create_unimp(s, &s->a2w, "bcm2835-a2w", A2W_OFFSET, 0x1000);
|
||||
create_unimp(s, &s->i2s, "bcm2835-i2s", I2S_OFFSET, 0x100);
|
||||
create_unimp(s, &s->smi, "bcm2835-smi", SMI_OFFSET, 0x100);
|
||||
create_unimp(s, &s->spi[0], "bcm2835-spi0", SPI0_OFFSET, 0x20);
|
||||
create_unimp(s, &s->bscsl, "bcm2835-spis", BSC_SL_OFFSET, 0x100);
|
||||
create_unimp(s, &s->i2c[0], "bcm2835-i2c0", BSC0_OFFSET, 0x20);
|
||||
create_unimp(s, &s->i2c[1], "bcm2835-i2c1", BSC1_OFFSET, 0x20);
|
||||
create_unimp(s, &s->i2c[2], "bcm2835-i2c2", BSC2_OFFSET, 0x20);
|
||||
create_unimp(s, &s->otp, "bcm2835-otp", OTP_OFFSET, 0x80);
|
||||
create_unimp(s, &s->dbus, "bcm2835-dbus", DBUS_OFFSET, 0x8000);
|
||||
create_unimp(s, &s->ave0, "bcm2835-ave0", AVE0_OFFSET, 0x8000);
|
||||
create_unimp(s, &s->dwc2, "dwc-usb2", USB_OTG_OFFSET, 0x1000);
|
||||
create_unimp(s, &s->sdramc, "bcm2835-sdramc", SDRAMC_OFFSET, 0x100);
|
||||
}
|
||||
|
||||
static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
|
||||
|
|
|
@ -126,7 +126,7 @@ static void bcm2836_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
/* set periphbase/CBAR value for CPU-local registers */
|
||||
object_property_set_int(OBJECT(&s->cpus[n]),
|
||||
BCM2836_PERI_BASE + MCORE_OFFSET,
|
||||
BCM2836_PERI_BASE + MSYNC_OFFSET,
|
||||
"reset-cbar", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
|
|
|
@ -843,13 +843,10 @@ static void mv88w8618_timer_tick(void *opaque)
|
|||
static void mv88w8618_timer_init(SysBusDevice *dev, mv88w8618_timer_state *s,
|
||||
uint32_t freq)
|
||||
{
|
||||
QEMUBH *bh;
|
||||
|
||||
sysbus_init_irq(dev, &s->irq);
|
||||
s->freq = freq;
|
||||
|
||||
bh = qemu_bh_new(mv88w8618_timer_tick, s);
|
||||
s->ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
|
||||
s->ptimer = ptimer_init(mv88w8618_timer_tick, s, PTIMER_POLICY_DEFAULT);
|
||||
}
|
||||
|
||||
static uint64_t mv88w8618_pit_read(void *opaque, hwaddr offset,
|
||||
|
@ -879,16 +876,19 @@ static void mv88w8618_pit_write(void *opaque, hwaddr offset,
|
|||
case MP_PIT_TIMER1_LENGTH ... MP_PIT_TIMER4_LENGTH:
|
||||
t = &s->timer[offset >> 2];
|
||||
t->limit = value;
|
||||
ptimer_transaction_begin(t->ptimer);
|
||||
if (t->limit > 0) {
|
||||
ptimer_set_limit(t->ptimer, t->limit, 1);
|
||||
} else {
|
||||
ptimer_stop(t->ptimer);
|
||||
}
|
||||
ptimer_transaction_commit(t->ptimer);
|
||||
break;
|
||||
|
||||
case MP_PIT_CONTROL:
|
||||
for (i = 0; i < 4; i++) {
|
||||
t = &s->timer[i];
|
||||
ptimer_transaction_begin(t->ptimer);
|
||||
if (value & 0xf && t->limit > 0) {
|
||||
ptimer_set_limit(t->ptimer, t->limit, 0);
|
||||
ptimer_set_freq(t->ptimer, t->freq);
|
||||
|
@ -896,6 +896,7 @@ static void mv88w8618_pit_write(void *opaque, hwaddr offset,
|
|||
} else {
|
||||
ptimer_stop(t->ptimer);
|
||||
}
|
||||
ptimer_transaction_commit(t->ptimer);
|
||||
value >>= 4;
|
||||
}
|
||||
break;
|
||||
|
@ -914,8 +915,11 @@ static void mv88w8618_pit_reset(DeviceState *d)
|
|||
int i;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
ptimer_stop(s->timer[i].ptimer);
|
||||
s->timer[i].limit = 0;
|
||||
mv88w8618_timer_state *t = &s->timer[i];
|
||||
ptimer_transaction_begin(t->ptimer);
|
||||
ptimer_stop(t->ptimer);
|
||||
ptimer_transaction_commit(t->ptimer);
|
||||
t->limit = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -230,7 +230,7 @@ static void raspi2_machine_init(MachineClass *mc)
|
|||
mc->max_cpus = BCM283X_NCPUS;
|
||||
mc->min_cpus = BCM283X_NCPUS;
|
||||
mc->default_cpus = BCM283X_NCPUS;
|
||||
mc->default_ram_size = 1024 * 1024 * 1024;
|
||||
mc->default_ram_size = 1 * GiB;
|
||||
mc->ignore_memory_transaction_failures = true;
|
||||
};
|
||||
DEFINE_MACHINE("raspi2", raspi2_machine_init)
|
||||
|
@ -252,7 +252,7 @@ static void raspi3_machine_init(MachineClass *mc)
|
|||
mc->max_cpus = BCM283X_NCPUS;
|
||||
mc->min_cpus = BCM283X_NCPUS;
|
||||
mc->default_cpus = BCM283X_NCPUS;
|
||||
mc->default_ram_size = 1024 * 1024 * 1024;
|
||||
mc->default_ram_size = 1 * GiB;
|
||||
}
|
||||
DEFINE_MACHINE("raspi3", raspi3_machine_init)
|
||||
#endif
|
||||
|
|
|
@ -327,6 +327,7 @@ static const FlashPartInfo known_devices[] = {
|
|||
{ INFO("w25q80", 0xef5014, 0, 64 << 10, 16, ER_4K) },
|
||||
{ INFO("w25q80bl", 0xef4014, 0, 64 << 10, 16, ER_4K) },
|
||||
{ INFO("w25q256", 0xef4019, 0, 64 << 10, 512, ER_4K) },
|
||||
{ INFO("w25q512jv", 0xef4020, 0, 64 << 10, 1024, ER_4K) },
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
|
|
|
@ -162,8 +162,9 @@ static void bcm2835_aux_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
switch (offset) {
|
||||
case AUX_ENABLES:
|
||||
if (value != 1) {
|
||||
qemu_log_mask(LOG_UNIMP, "%s: unsupported attempt to enable SPI "
|
||||
"or disable UART\n", __func__);
|
||||
qemu_log_mask(LOG_UNIMP, "%s: unsupported attempt to enable SPI"
|
||||
" or disable UART: 0x%"PRIx64"\n",
|
||||
__func__, value);
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
154
hw/core/ptimer.c
154
hw/core/ptimer.c
|
@ -31,6 +31,16 @@ struct ptimer_state
|
|||
uint8_t policy_mask;
|
||||
QEMUBH *bh;
|
||||
QEMUTimer *timer;
|
||||
ptimer_cb callback;
|
||||
void *callback_opaque;
|
||||
/*
|
||||
* These track whether we're in a transaction block, and if we
|
||||
* need to do a timer reload when the block finishes. They don't
|
||||
* need to be migrated because migration can never happen in the
|
||||
* middle of a transaction block.
|
||||
*/
|
||||
bool in_transaction;
|
||||
bool need_reload;
|
||||
};
|
||||
|
||||
/* Use a bottom-half routine to avoid reentrancy issues. */
|
||||
|
@ -39,13 +49,16 @@ static void ptimer_trigger(ptimer_state *s)
|
|||
if (s->bh) {
|
||||
replay_bh_schedule_event(s->bh);
|
||||
}
|
||||
if (s->callback) {
|
||||
s->callback(s->callback_opaque);
|
||||
}
|
||||
}
|
||||
|
||||
static void ptimer_reload(ptimer_state *s, int delta_adjust)
|
||||
{
|
||||
uint32_t period_frac = s->period_frac;
|
||||
uint64_t period = s->period;
|
||||
uint64_t delta = s->delta;
|
||||
uint32_t period_frac;
|
||||
uint64_t period;
|
||||
uint64_t delta;
|
||||
bool suppress_trigger = false;
|
||||
|
||||
/*
|
||||
|
@ -58,11 +71,20 @@ static void ptimer_reload(ptimer_state *s, int delta_adjust)
|
|||
(s->policy_mask & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT)) {
|
||||
suppress_trigger = true;
|
||||
}
|
||||
if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)
|
||||
if (s->delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)
|
||||
&& !suppress_trigger) {
|
||||
ptimer_trigger(s);
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that ptimer_trigger() might call the device callback function,
|
||||
* which can then modify timer state, so we must not cache any fields
|
||||
* from ptimer_state until after we have called it.
|
||||
*/
|
||||
delta = s->delta;
|
||||
period = s->period;
|
||||
period_frac = s->period_frac;
|
||||
|
||||
if (delta == 0 && !(s->policy_mask & PTIMER_POLICY_NO_IMMEDIATE_RELOAD)) {
|
||||
delta = s->delta = s->limit;
|
||||
}
|
||||
|
@ -136,6 +158,15 @@ static void ptimer_tick(void *opaque)
|
|||
ptimer_state *s = (ptimer_state *)opaque;
|
||||
bool trigger = true;
|
||||
|
||||
/*
|
||||
* We perform all the tick actions within a begin/commit block
|
||||
* because the callback function that ptimer_trigger() calls
|
||||
* might make calls into the ptimer APIs that provoke another
|
||||
* trigger, and we want that to cause the callback function
|
||||
* to be called iteratively, not recursively.
|
||||
*/
|
||||
ptimer_transaction_begin(s);
|
||||
|
||||
if (s->enabled == 2) {
|
||||
s->delta = 0;
|
||||
s->enabled = 0;
|
||||
|
@ -164,6 +195,8 @@ static void ptimer_tick(void *opaque)
|
|||
if (trigger) {
|
||||
ptimer_trigger(s);
|
||||
}
|
||||
|
||||
ptimer_transaction_commit(s);
|
||||
}
|
||||
|
||||
uint64_t ptimer_get_count(ptimer_state *s)
|
||||
|
@ -263,10 +296,15 @@ uint64_t ptimer_get_count(ptimer_state *s)
|
|||
|
||||
void ptimer_set_count(ptimer_state *s, uint64_t count)
|
||||
{
|
||||
assert(s->in_transaction || !s->callback);
|
||||
s->delta = count;
|
||||
if (s->enabled) {
|
||||
s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
ptimer_reload(s, 0);
|
||||
if (!s->callback) {
|
||||
s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
ptimer_reload(s, 0);
|
||||
} else {
|
||||
s->need_reload = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -274,6 +312,8 @@ void ptimer_run(ptimer_state *s, int oneshot)
|
|||
{
|
||||
bool was_disabled = !s->enabled;
|
||||
|
||||
assert(s->in_transaction || !s->callback);
|
||||
|
||||
if (was_disabled && s->period == 0) {
|
||||
if (!qtest_enabled()) {
|
||||
fprintf(stderr, "Timer with period zero, disabling\n");
|
||||
|
@ -282,8 +322,12 @@ void ptimer_run(ptimer_state *s, int oneshot)
|
|||
}
|
||||
s->enabled = oneshot ? 2 : 1;
|
||||
if (was_disabled) {
|
||||
s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
ptimer_reload(s, 0);
|
||||
if (!s->callback) {
|
||||
s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
ptimer_reload(s, 0);
|
||||
} else {
|
||||
s->need_reload = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,35 +335,50 @@ void ptimer_run(ptimer_state *s, int oneshot)
|
|||
is immediately restarted. */
|
||||
void ptimer_stop(ptimer_state *s)
|
||||
{
|
||||
assert(s->in_transaction || !s->callback);
|
||||
|
||||
if (!s->enabled)
|
||||
return;
|
||||
|
||||
s->delta = ptimer_get_count(s);
|
||||
timer_del(s->timer);
|
||||
s->enabled = 0;
|
||||
if (s->callback) {
|
||||
s->need_reload = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set counter increment interval in nanoseconds. */
|
||||
void ptimer_set_period(ptimer_state *s, int64_t period)
|
||||
{
|
||||
assert(s->in_transaction || !s->callback);
|
||||
s->delta = ptimer_get_count(s);
|
||||
s->period = period;
|
||||
s->period_frac = 0;
|
||||
if (s->enabled) {
|
||||
s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
ptimer_reload(s, 0);
|
||||
if (!s->callback) {
|
||||
s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
ptimer_reload(s, 0);
|
||||
} else {
|
||||
s->need_reload = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set counter frequency in Hz. */
|
||||
void ptimer_set_freq(ptimer_state *s, uint32_t freq)
|
||||
{
|
||||
assert(s->in_transaction || !s->callback);
|
||||
s->delta = ptimer_get_count(s);
|
||||
s->period = 1000000000ll / freq;
|
||||
s->period_frac = (1000000000ll << 32) / freq;
|
||||
if (s->enabled) {
|
||||
s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
ptimer_reload(s, 0);
|
||||
if (!s->callback) {
|
||||
s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
ptimer_reload(s, 0);
|
||||
} else {
|
||||
s->need_reload = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -327,12 +386,17 @@ void ptimer_set_freq(ptimer_state *s, uint32_t freq)
|
|||
count = limit. */
|
||||
void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
|
||||
{
|
||||
assert(s->in_transaction || !s->callback);
|
||||
s->limit = limit;
|
||||
if (reload)
|
||||
s->delta = limit;
|
||||
if (s->enabled && reload) {
|
||||
s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
ptimer_reload(s, 0);
|
||||
if (!s->callback) {
|
||||
s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
ptimer_reload(s, 0);
|
||||
} else {
|
||||
s->need_reload = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -341,6 +405,32 @@ uint64_t ptimer_get_limit(ptimer_state *s)
|
|||
return s->limit;
|
||||
}
|
||||
|
||||
void ptimer_transaction_begin(ptimer_state *s)
|
||||
{
|
||||
assert(!s->in_transaction || !s->callback);
|
||||
s->in_transaction = true;
|
||||
s->need_reload = false;
|
||||
}
|
||||
|
||||
void ptimer_transaction_commit(ptimer_state *s)
|
||||
{
|
||||
assert(s->in_transaction);
|
||||
/*
|
||||
* We must loop here because ptimer_reload() can call the callback
|
||||
* function, which might then update ptimer state in a way that
|
||||
* means we need to do another reload and possibly another callback.
|
||||
* A disabled timer never needs reloading (and if we don't check
|
||||
* this then we loop forever if ptimer_reload() disables the timer).
|
||||
*/
|
||||
while (s->need_reload && s->enabled) {
|
||||
s->need_reload = false;
|
||||
s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||
ptimer_reload(s, 0);
|
||||
}
|
||||
/* Now we've finished reload we can leave the transaction block. */
|
||||
s->in_transaction = false;
|
||||
}
|
||||
|
||||
const VMStateDescription vmstate_ptimer = {
|
||||
.name = "ptimer",
|
||||
.version_id = 1,
|
||||
|
@ -358,7 +448,7 @@ const VMStateDescription vmstate_ptimer = {
|
|||
}
|
||||
};
|
||||
|
||||
ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask)
|
||||
ptimer_state *ptimer_init_with_bh(QEMUBH *bh, uint8_t policy_mask)
|
||||
{
|
||||
ptimer_state *s;
|
||||
|
||||
|
@ -377,9 +467,41 @@ ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask)
|
|||
return s;
|
||||
}
|
||||
|
||||
ptimer_state *ptimer_init(ptimer_cb callback, void *callback_opaque,
|
||||
uint8_t policy_mask)
|
||||
{
|
||||
ptimer_state *s;
|
||||
|
||||
/*
|
||||
* The callback function is mandatory; so we use it to distinguish
|
||||
* old-style QEMUBH ptimers from new transaction API ptimers.
|
||||
* (ptimer_init_with_bh() allows a NULL bh pointer and at least
|
||||
* one device (digic-timer) passes NULL, so it's not the case
|
||||
* that either s->bh != NULL or s->callback != NULL.)
|
||||
*/
|
||||
assert(callback);
|
||||
|
||||
s = g_new0(ptimer_state, 1);
|
||||
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ptimer_tick, s);
|
||||
s->policy_mask = policy_mask;
|
||||
s->callback = callback;
|
||||
s->callback_opaque = callback_opaque;
|
||||
|
||||
/*
|
||||
* These two policies are incompatible -- trigger-on-decrement implies
|
||||
* a timer trigger when the count becomes 0, but no-immediate-trigger
|
||||
* implies a trigger when the count stops being 0.
|
||||
*/
|
||||
assert(!((policy_mask & PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT) &&
|
||||
(policy_mask & PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)));
|
||||
return s;
|
||||
}
|
||||
|
||||
void ptimer_free(ptimer_state *s)
|
||||
{
|
||||
qemu_bh_delete(s->bh);
|
||||
if (s->bh) {
|
||||
qemu_bh_delete(s->bh);
|
||||
}
|
||||
timer_free(s->timer);
|
||||
g_free(s);
|
||||
}
|
||||
|
|
|
@ -425,7 +425,7 @@ static void bcm2835_fb_realize(DeviceState *dev, Error **errp)
|
|||
s->initial_config.base = s->vcram_base + BCM2835_FB_OFFSET;
|
||||
|
||||
s->dma_mr = MEMORY_REGION(obj);
|
||||
address_space_init(&s->dma_as, s->dma_mr, NULL);
|
||||
address_space_init(&s->dma_as, s->dma_mr, TYPE_BCM2835_FB "-memory");
|
||||
|
||||
bcm2835_fb_reset(dev);
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ static uint64_t bcm2835_dma_read(BCM2835DMAState *s, hwaddr offset,
|
|||
res = ch->debug;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
break;
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ static void bcm2835_dma_write(BCM2835DMAState *s, hwaddr offset,
|
|||
ch->debug = value;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
break;
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ static uint64_t bcm2835_dma0_read(void *opaque, hwaddr offset, unsigned size)
|
|||
case BCM2708_DMA_ENABLE:
|
||||
return s->enable;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
return 0;
|
||||
}
|
||||
|
@ -274,7 +274,7 @@ static void bcm2835_dma0_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
s->enable = (value & 0xffff);
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
}
|
||||
}
|
||||
|
@ -383,7 +383,7 @@ static void bcm2835_dma_realize(DeviceState *dev, Error **errp)
|
|||
}
|
||||
|
||||
s->dma_mr = MEMORY_REGION(obj);
|
||||
address_space_init(&s->dma_as, s->dma_mr, NULL);
|
||||
address_space_init(&s->dma_as, s->dma_mr, TYPE_BCM2835_DMA "-memory");
|
||||
|
||||
bcm2835_dma_reset(dev);
|
||||
}
|
||||
|
|
|
@ -552,7 +552,7 @@ static void xilinx_axidma_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
st->nr = i;
|
||||
st->bh = qemu_bh_new(timer_hit, st);
|
||||
st->ptimer = ptimer_init(st->bh, PTIMER_POLICY_DEFAULT);
|
||||
st->ptimer = ptimer_init_with_bh(st->bh, PTIMER_POLICY_DEFAULT);
|
||||
ptimer_set_freq(st->ptimer, s->freqhz);
|
||||
}
|
||||
return;
|
||||
|
|
|
@ -169,6 +169,48 @@
|
|||
#define GPIO_3_6V_MEM_SIZE 0x1F0
|
||||
#define GPIO_3_6V_REG_ARRAY_SIZE (GPIO_3_6V_MEM_SIZE >> 2)
|
||||
|
||||
/* AST2600 only - 1.8V gpios */
|
||||
/*
|
||||
* The AST2600 has same 3.6V gpios as the AST2400 (memory offsets 0x0-0x198)
|
||||
* and addtional 1.8V gpios (memory offsets 0x800-0x9D4).
|
||||
*/
|
||||
#define GPIO_1_8V_REG_OFFSET 0x800
|
||||
#define GPIO_1_8V_ABCD_DATA_VALUE ((0x800 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_ABCD_DIRECTION ((0x804 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_ABCD_INT_ENABLE ((0x808 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_ABCD_INT_SENS_0 ((0x80C - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_ABCD_INT_SENS_1 ((0x810 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_ABCD_INT_SENS_2 ((0x814 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_ABCD_INT_STATUS ((0x818 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_ABCD_RESET_TOLERANT ((0x81C - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_E_DATA_VALUE ((0x820 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_E_DIRECTION ((0x824 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_E_INT_ENABLE ((0x828 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_E_INT_SENS_0 ((0x82C - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_E_INT_SENS_1 ((0x830 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_E_INT_SENS_2 ((0x834 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_E_INT_STATUS ((0x838 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_E_RESET_TOLERANT ((0x83C - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_ABCD_DEBOUNCE_1 ((0x840 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_ABCD_DEBOUNCE_2 ((0x844 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_E_DEBOUNCE_1 ((0x848 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_E_DEBOUNCE_2 ((0x84C - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_DEBOUNCE_TIME_1 ((0x850 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_DEBOUNCE_TIME_2 ((0x854 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_DEBOUNCE_TIME_3 ((0x858 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_ABCD_COMMAND_SRC_0 ((0x860 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_ABCD_COMMAND_SRC_1 ((0x864 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_E_COMMAND_SRC_0 ((0x868 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_E_COMMAND_SRC_1 ((0x86C - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_ABCD_DATA_READ ((0x8C0 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_E_DATA_READ ((0x8C4 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_ABCD_INPUT_MASK ((0x9D0 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_E_INPUT_MASK ((0x9D4 - GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_1_8V_MEM_SIZE 0x9D8
|
||||
#define GPIO_1_8V_REG_ARRAY_SIZE ((GPIO_1_8V_MEM_SIZE - \
|
||||
GPIO_1_8V_REG_OFFSET) >> 2)
|
||||
#define GPIO_MAX_MEM_SIZE MAX(GPIO_3_6V_MEM_SIZE, GPIO_1_8V_MEM_SIZE)
|
||||
|
||||
static int aspeed_evaluate_irq(GPIOSets *regs, int gpio_prev_high, int gpio)
|
||||
{
|
||||
uint32_t falling_edge = 0, rising_edge = 0;
|
||||
|
@ -465,6 +507,39 @@ static const AspeedGPIOReg aspeed_3_6v_gpios[GPIO_3_6V_REG_ARRAY_SIZE] = {
|
|||
[GPIO_AC_INPUT_MASK] = { 7, gpio_reg_input_mask },
|
||||
};
|
||||
|
||||
static const AspeedGPIOReg aspeed_1_8v_gpios[GPIO_1_8V_REG_ARRAY_SIZE] = {
|
||||
/* 1.8V Set ABCD */
|
||||
[GPIO_1_8V_ABCD_DATA_VALUE] = {0, gpio_reg_data_value},
|
||||
[GPIO_1_8V_ABCD_DIRECTION] = {0, gpio_reg_direction},
|
||||
[GPIO_1_8V_ABCD_INT_ENABLE] = {0, gpio_reg_int_enable},
|
||||
[GPIO_1_8V_ABCD_INT_SENS_0] = {0, gpio_reg_int_sens_0},
|
||||
[GPIO_1_8V_ABCD_INT_SENS_1] = {0, gpio_reg_int_sens_1},
|
||||
[GPIO_1_8V_ABCD_INT_SENS_2] = {0, gpio_reg_int_sens_2},
|
||||
[GPIO_1_8V_ABCD_INT_STATUS] = {0, gpio_reg_int_status},
|
||||
[GPIO_1_8V_ABCD_RESET_TOLERANT] = {0, gpio_reg_reset_tolerant},
|
||||
[GPIO_1_8V_ABCD_DEBOUNCE_1] = {0, gpio_reg_debounce_1},
|
||||
[GPIO_1_8V_ABCD_DEBOUNCE_2] = {0, gpio_reg_debounce_2},
|
||||
[GPIO_1_8V_ABCD_COMMAND_SRC_0] = {0, gpio_reg_cmd_source_0},
|
||||
[GPIO_1_8V_ABCD_COMMAND_SRC_1] = {0, gpio_reg_cmd_source_1},
|
||||
[GPIO_1_8V_ABCD_DATA_READ] = {0, gpio_reg_data_read},
|
||||
[GPIO_1_8V_ABCD_INPUT_MASK] = {0, gpio_reg_input_mask},
|
||||
/* 1.8V Set E */
|
||||
[GPIO_1_8V_E_DATA_VALUE] = {1, gpio_reg_data_value},
|
||||
[GPIO_1_8V_E_DIRECTION] = {1, gpio_reg_direction},
|
||||
[GPIO_1_8V_E_INT_ENABLE] = {1, gpio_reg_int_enable},
|
||||
[GPIO_1_8V_E_INT_SENS_0] = {1, gpio_reg_int_sens_0},
|
||||
[GPIO_1_8V_E_INT_SENS_1] = {1, gpio_reg_int_sens_1},
|
||||
[GPIO_1_8V_E_INT_SENS_2] = {1, gpio_reg_int_sens_2},
|
||||
[GPIO_1_8V_E_INT_STATUS] = {1, gpio_reg_int_status},
|
||||
[GPIO_1_8V_E_RESET_TOLERANT] = {1, gpio_reg_reset_tolerant},
|
||||
[GPIO_1_8V_E_DEBOUNCE_1] = {1, gpio_reg_debounce_1},
|
||||
[GPIO_1_8V_E_DEBOUNCE_2] = {1, gpio_reg_debounce_2},
|
||||
[GPIO_1_8V_E_COMMAND_SRC_0] = {1, gpio_reg_cmd_source_0},
|
||||
[GPIO_1_8V_E_COMMAND_SRC_1] = {1, gpio_reg_cmd_source_1},
|
||||
[GPIO_1_8V_E_DATA_READ] = {1, gpio_reg_data_read},
|
||||
[GPIO_1_8V_E_INPUT_MASK] = {1, gpio_reg_input_mask},
|
||||
};
|
||||
|
||||
static uint64_t aspeed_gpio_read(void *opaque, hwaddr offset, uint32_t size)
|
||||
{
|
||||
AspeedGPIOState *s = ASPEED_GPIO(opaque);
|
||||
|
@ -663,8 +738,11 @@ static void aspeed_gpio_get_pin(Object *obj, Visitor *v, const char *name,
|
|||
int set_idx, group_idx = 0;
|
||||
|
||||
if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) {
|
||||
error_setg(errp, "%s: error reading %s", __func__, name);
|
||||
return;
|
||||
/* 1.8V gpio */
|
||||
if (sscanf(name, "gpio%3s%1d", group, &pin) != 2) {
|
||||
error_setg(errp, "%s: error reading %s", __func__, name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
set_idx = get_set_idx(s, group, &group_idx);
|
||||
if (set_idx == -1) {
|
||||
|
@ -692,8 +770,11 @@ static void aspeed_gpio_set_pin(Object *obj, Visitor *v, const char *name,
|
|||
return;
|
||||
}
|
||||
if (sscanf(name, "gpio%2[A-Z]%1d", group, &pin) != 2) {
|
||||
error_setg(errp, "%s: error reading %s", __func__, name);
|
||||
return;
|
||||
/* 1.8V gpio */
|
||||
if (sscanf(name, "gpio%3s%1d", group, &pin) != 2) {
|
||||
error_setg(errp, "%s: error reading %s", __func__, name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
set_idx = get_set_idx(s, group, &group_idx);
|
||||
if (set_idx == -1) {
|
||||
|
@ -726,6 +807,21 @@ static const GPIOSetProperties ast2500_set_props[] = {
|
|||
[7] = {0x000000ff, 0x000000ff, {"AC"} },
|
||||
};
|
||||
|
||||
static GPIOSetProperties ast2600_3_6v_set_props[] = {
|
||||
[0] = {0xffffffff, 0xffffffff, {"A", "B", "C", "D"} },
|
||||
[1] = {0xffffffff, 0xffffffff, {"E", "F", "G", "H"} },
|
||||
[2] = {0xffffffff, 0xffffffff, {"I", "J", "K", "L"} },
|
||||
[3] = {0xffffffff, 0xffffffff, {"M", "N", "O", "P"} },
|
||||
[4] = {0xffffffff, 0xffffffff, {"Q", "R", "S", "T"} },
|
||||
[5] = {0xffffffff, 0x0000ffff, {"U", "V", "W", "X"} },
|
||||
[6] = {0xffff0000, 0x0fff0000, {"Y", "Z", "", ""} },
|
||||
};
|
||||
|
||||
static GPIOSetProperties ast2600_1_8v_set_props[] = {
|
||||
[0] = {0xffffffff, 0xffffffff, {"18A", "18B", "18C", "18D"} },
|
||||
[1] = {0x0000000f, 0x0000000f, {"18E"} },
|
||||
};
|
||||
|
||||
static const MemoryRegionOps aspeed_gpio_ops = {
|
||||
.read = aspeed_gpio_read,
|
||||
.write = aspeed_gpio_write,
|
||||
|
@ -758,7 +854,7 @@ static void aspeed_gpio_realize(DeviceState *dev, Error **errp)
|
|||
}
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_gpio_ops, s,
|
||||
TYPE_ASPEED_GPIO, GPIO_3_6V_MEM_SIZE);
|
||||
TYPE_ASPEED_GPIO, GPIO_MAX_MEM_SIZE);
|
||||
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
|
@ -851,6 +947,26 @@ static void aspeed_gpio_2500_class_init(ObjectClass *klass, void *data)
|
|||
agc->reg_table = aspeed_3_6v_gpios;
|
||||
}
|
||||
|
||||
static void aspeed_gpio_ast2600_3_6v_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
AspeedGPIOClass *agc = ASPEED_GPIO_CLASS(klass);
|
||||
|
||||
agc->props = ast2600_3_6v_set_props;
|
||||
agc->nr_gpio_pins = 208;
|
||||
agc->nr_gpio_sets = 7;
|
||||
agc->reg_table = aspeed_3_6v_gpios;
|
||||
}
|
||||
|
||||
static void aspeed_gpio_ast2600_1_8v_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
AspeedGPIOClass *agc = ASPEED_GPIO_CLASS(klass);
|
||||
|
||||
agc->props = ast2600_1_8v_set_props;
|
||||
agc->nr_gpio_pins = 36;
|
||||
agc->nr_gpio_sets = 2;
|
||||
agc->reg_table = aspeed_1_8v_gpios;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_gpio_info = {
|
||||
.name = TYPE_ASPEED_GPIO,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
|
@ -874,11 +990,27 @@ static const TypeInfo aspeed_gpio_ast2500_info = {
|
|||
.instance_init = aspeed_gpio_init,
|
||||
};
|
||||
|
||||
static const TypeInfo aspeed_gpio_ast2600_3_6v_info = {
|
||||
.name = TYPE_ASPEED_GPIO "-ast2600",
|
||||
.parent = TYPE_ASPEED_GPIO,
|
||||
.class_init = aspeed_gpio_ast2600_3_6v_class_init,
|
||||
.instance_init = aspeed_gpio_init,
|
||||
};
|
||||
|
||||
static const TypeInfo aspeed_gpio_ast2600_1_8v_info = {
|
||||
.name = TYPE_ASPEED_GPIO "-ast2600-1_8v",
|
||||
.parent = TYPE_ASPEED_GPIO,
|
||||
.class_init = aspeed_gpio_ast2600_1_8v_class_init,
|
||||
.instance_init = aspeed_gpio_init,
|
||||
};
|
||||
|
||||
static void aspeed_gpio_register_types(void)
|
||||
{
|
||||
type_register_static(&aspeed_gpio_info);
|
||||
type_register_static(&aspeed_gpio_ast2400_info);
|
||||
type_register_static(&aspeed_gpio_ast2500_info);
|
||||
type_register_static(&aspeed_gpio_ast2600_3_6v_info);
|
||||
type_register_static(&aspeed_gpio_ast2600_1_8v_info);
|
||||
}
|
||||
|
||||
type_init(aspeed_gpio_register_types);
|
||||
|
|
|
@ -145,10 +145,12 @@ static inline bool aspeed_i2c_bus_is_enabled(AspeedI2CBus *bus)
|
|||
|
||||
static inline void aspeed_i2c_bus_raise_interrupt(AspeedI2CBus *bus)
|
||||
{
|
||||
AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
|
||||
|
||||
bus->intr_status &= bus->intr_ctrl;
|
||||
if (bus->intr_status) {
|
||||
bus->controller->intr_status |= 1 << bus->id;
|
||||
qemu_irq_raise(bus->controller->irq);
|
||||
qemu_irq_raise(aic->bus_get_irq(bus));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -273,6 +275,7 @@ static void aspeed_i2c_bus_write(void *opaque, hwaddr offset,
|
|||
uint64_t value, unsigned size)
|
||||
{
|
||||
AspeedI2CBus *bus = opaque;
|
||||
AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(bus->controller);
|
||||
bool handle_rx;
|
||||
|
||||
switch (offset) {
|
||||
|
@ -299,7 +302,7 @@ static void aspeed_i2c_bus_write(void *opaque, hwaddr offset,
|
|||
bus->intr_status &= ~(value & 0x7FFF);
|
||||
if (!bus->intr_status) {
|
||||
bus->controller->intr_status &= ~(1 << bus->id);
|
||||
qemu_irq_lower(bus->controller->irq);
|
||||
qemu_irq_lower(aic->bus_get_irq(bus));
|
||||
}
|
||||
if (handle_rx && (bus->cmd & (I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST))) {
|
||||
aspeed_i2c_handle_rx_cmd(bus);
|
||||
|
@ -408,10 +411,11 @@ static void aspeed_i2c_reset(DeviceState *dev)
|
|||
{
|
||||
int i;
|
||||
AspeedI2CState *s = ASPEED_I2C(dev);
|
||||
AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(s);
|
||||
|
||||
s->intr_status = 0;
|
||||
|
||||
for (i = 0; i < ASPEED_I2C_NR_BUSSES; i++) {
|
||||
for (i = 0; i < aic->num_busses; i++) {
|
||||
s->busses[i].intr_ctrl = 0;
|
||||
s->busses[i].intr_status = 0;
|
||||
s->busses[i].cmd = 0;
|
||||
|
@ -421,7 +425,7 @@ static void aspeed_i2c_reset(DeviceState *dev)
|
|||
}
|
||||
|
||||
/*
|
||||
* Address Definitions
|
||||
* Address Definitions (AST2400 and AST2500)
|
||||
*
|
||||
* 0x000 ... 0x03F: Global Register
|
||||
* 0x040 ... 0x07F: Device 1
|
||||
|
@ -446,22 +450,26 @@ static void aspeed_i2c_realize(DeviceState *dev, Error **errp)
|
|||
int i;
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
AspeedI2CState *s = ASPEED_I2C(dev);
|
||||
AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(s);
|
||||
|
||||
sysbus_init_irq(sbd, &s->irq);
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_i2c_ctrl_ops, s,
|
||||
"aspeed.i2c", 0x1000);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
|
||||
for (i = 0; i < ASPEED_I2C_NR_BUSSES; i++) {
|
||||
char name[16];
|
||||
int offset = i < 7 ? 1 : 5;
|
||||
for (i = 0; i < aic->num_busses; i++) {
|
||||
char name[32];
|
||||
int offset = i < aic->gap ? 1 : 5;
|
||||
|
||||
sysbus_init_irq(sbd, &s->busses[i].irq);
|
||||
snprintf(name, sizeof(name), "aspeed.i2c.%d", i);
|
||||
s->busses[i].controller = s;
|
||||
s->busses[i].id = i;
|
||||
s->busses[i].bus = i2c_init_bus(dev, name);
|
||||
memory_region_init_io(&s->busses[i].mr, OBJECT(dev),
|
||||
&aspeed_i2c_bus_ops, &s->busses[i], name, 0x40);
|
||||
memory_region_add_subregion(&s->iomem, 0x40 * (i + offset),
|
||||
&aspeed_i2c_bus_ops, &s->busses[i], name,
|
||||
aic->reg_size);
|
||||
memory_region_add_subregion(&s->iomem, aic->reg_size * (i + offset),
|
||||
&s->busses[i].mr);
|
||||
}
|
||||
}
|
||||
|
@ -481,11 +489,88 @@ static const TypeInfo aspeed_i2c_info = {
|
|||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(AspeedI2CState),
|
||||
.class_init = aspeed_i2c_class_init,
|
||||
.class_size = sizeof(AspeedI2CClass),
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static qemu_irq aspeed_2400_i2c_bus_get_irq(AspeedI2CBus *bus)
|
||||
{
|
||||
return bus->controller->irq;
|
||||
}
|
||||
|
||||
static void aspeed_2400_i2c_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedI2CClass *aic = ASPEED_I2C_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2400 I2C Controller";
|
||||
|
||||
aic->num_busses = 14;
|
||||
aic->reg_size = 0x40;
|
||||
aic->gap = 7;
|
||||
aic->bus_get_irq = aspeed_2400_i2c_bus_get_irq;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2400_i2c_info = {
|
||||
.name = TYPE_ASPEED_2400_I2C,
|
||||
.parent = TYPE_ASPEED_I2C,
|
||||
.class_init = aspeed_2400_i2c_class_init,
|
||||
};
|
||||
|
||||
static qemu_irq aspeed_2500_i2c_bus_get_irq(AspeedI2CBus *bus)
|
||||
{
|
||||
return bus->controller->irq;
|
||||
}
|
||||
|
||||
static void aspeed_2500_i2c_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedI2CClass *aic = ASPEED_I2C_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2500 I2C Controller";
|
||||
|
||||
aic->num_busses = 14;
|
||||
aic->reg_size = 0x40;
|
||||
aic->gap = 7;
|
||||
aic->bus_get_irq = aspeed_2500_i2c_bus_get_irq;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2500_i2c_info = {
|
||||
.name = TYPE_ASPEED_2500_I2C,
|
||||
.parent = TYPE_ASPEED_I2C,
|
||||
.class_init = aspeed_2500_i2c_class_init,
|
||||
};
|
||||
|
||||
static qemu_irq aspeed_2600_i2c_bus_get_irq(AspeedI2CBus *bus)
|
||||
{
|
||||
return bus->irq;
|
||||
}
|
||||
|
||||
static void aspeed_2600_i2c_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedI2CClass *aic = ASPEED_I2C_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2600 I2C Controller";
|
||||
|
||||
aic->num_busses = 16;
|
||||
aic->reg_size = 0x80;
|
||||
aic->gap = -1; /* no gap */
|
||||
aic->bus_get_irq = aspeed_2600_i2c_bus_get_irq;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2600_i2c_info = {
|
||||
.name = TYPE_ASPEED_2600_I2C,
|
||||
.parent = TYPE_ASPEED_I2C,
|
||||
.class_init = aspeed_2600_i2c_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_i2c_register_types(void)
|
||||
{
|
||||
type_register_static(&aspeed_i2c_info);
|
||||
type_register_static(&aspeed_2400_i2c_info);
|
||||
type_register_static(&aspeed_2500_i2c_info);
|
||||
type_register_static(&aspeed_2600_i2c_info);
|
||||
}
|
||||
|
||||
type_init(aspeed_i2c_register_types)
|
||||
|
@ -494,9 +579,10 @@ type_init(aspeed_i2c_register_types)
|
|||
I2CBus *aspeed_i2c_get_bus(DeviceState *dev, int busnr)
|
||||
{
|
||||
AspeedI2CState *s = ASPEED_I2C(dev);
|
||||
AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(s);
|
||||
I2CBus *bus = NULL;
|
||||
|
||||
if (busnr >= 0 && busnr < ASPEED_I2C_NR_BUSSES) {
|
||||
if (busnr >= 0 && busnr < aic->num_busses) {
|
||||
bus = s->busses[busnr].bus;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level)
|
|||
* has separate fields in the irq number for type,
|
||||
* CPU number and interrupt number.
|
||||
*/
|
||||
int kvm_irq, irqtype, cpu;
|
||||
int irqtype, cpu;
|
||||
|
||||
if (irq < (num_irq - GIC_INTERNAL)) {
|
||||
/* External interrupt. The kernel numbers these like the GIC
|
||||
|
@ -72,10 +72,7 @@ void kvm_arm_gic_set_irq(uint32_t num_irq, int irq, int level)
|
|||
cpu = irq / GIC_INTERNAL;
|
||||
irq %= GIC_INTERNAL;
|
||||
}
|
||||
kvm_irq = (irqtype << KVM_ARM_IRQ_TYPE_SHIFT)
|
||||
| (cpu << KVM_ARM_IRQ_VCPU_SHIFT) | irq;
|
||||
|
||||
kvm_set_irq(kvm_state, kvm_irq, !!level);
|
||||
kvm_arm_set_irq(cpu, irqtype, irq, !!level);
|
||||
}
|
||||
|
||||
static void kvm_arm_gicv2_set_irq(void *opaque, int irq, int level)
|
||||
|
|
|
@ -264,7 +264,7 @@ static uint64_t bcm2836_control_read(void *opaque, hwaddr offset, unsigned size)
|
|||
} else if (offset >= REG_MBOX0_RDCLR && offset < REG_LIMIT) {
|
||||
return s->mailboxes[(offset - REG_MBOX0_RDCLR) >> 2];
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
return 0;
|
||||
}
|
||||
|
@ -293,8 +293,9 @@ static void bcm2836_control_write(void *opaque, hwaddr offset,
|
|||
} else if (offset >= REG_MBOX0_RDCLR && offset < REG_LIMIT) {
|
||||
s->mailboxes[(offset - REG_MBOX0_RDCLR) >> 2] &= ~val;
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx
|
||||
" value 0x%"PRIx64"\n",
|
||||
__func__, offset, val);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -141,7 +141,7 @@ static m5206_timer_state *m5206_timer_init(qemu_irq irq)
|
|||
|
||||
s = g_new0(m5206_timer_state, 1);
|
||||
bh = qemu_bh_new(m5206_timer_trigger, s);
|
||||
s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
|
||||
s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
|
||||
s->irq = irq;
|
||||
m5206_timer_reset(s);
|
||||
return s;
|
||||
|
|
|
@ -192,7 +192,7 @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
|
|||
for (i = 0; i < 2; i++) {
|
||||
s = g_new0(m5208_timer_state, 1);
|
||||
bh = qemu_bh_new(m5208_timer_trigger, s);
|
||||
s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
|
||||
s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
|
||||
memory_region_init_io(&s->iomem, NULL, &m5208_timer_ops, s,
|
||||
"m5208-timer", 0x00004000);
|
||||
memory_region_add_subregion(address_space, 0xfc080000 + 0x4000 * i,
|
||||
|
|
|
@ -88,6 +88,36 @@
|
|||
#define BMC_REV TO_REG(0x19C)
|
||||
#define BMC_DEV_ID TO_REG(0x1A4)
|
||||
|
||||
#define AST2600_PROT_KEY TO_REG(0x00)
|
||||
#define AST2600_SILICON_REV TO_REG(0x04)
|
||||
#define AST2600_SILICON_REV2 TO_REG(0x14)
|
||||
#define AST2600_SYS_RST_CTRL TO_REG(0x40)
|
||||
#define AST2600_SYS_RST_CTRL_CLR TO_REG(0x44)
|
||||
#define AST2600_SYS_RST_CTRL2 TO_REG(0x50)
|
||||
#define AST2600_SYS_RST_CTRL2_CLR TO_REG(0x54)
|
||||
#define AST2600_CLK_STOP_CTRL TO_REG(0x80)
|
||||
#define AST2600_CLK_STOP_CTRL_CLR TO_REG(0x84)
|
||||
#define AST2600_CLK_STOP_CTRL2 TO_REG(0x90)
|
||||
#define AST2600_CLK_STOP_CTR2L_CLR TO_REG(0x94)
|
||||
#define AST2600_SDRAM_HANDSHAKE TO_REG(0x100)
|
||||
#define AST2600_HPLL_PARAM TO_REG(0x200)
|
||||
#define AST2600_HPLL_EXT TO_REG(0x204)
|
||||
#define AST2600_MPLL_EXT TO_REG(0x224)
|
||||
#define AST2600_EPLL_EXT TO_REG(0x244)
|
||||
#define AST2600_CLK_SEL TO_REG(0x300)
|
||||
#define AST2600_CLK_SEL2 TO_REG(0x304)
|
||||
#define AST2600_CLK_SEL3 TO_REG(0x310)
|
||||
#define AST2600_HW_STRAP1 TO_REG(0x500)
|
||||
#define AST2600_HW_STRAP1_CLR TO_REG(0x504)
|
||||
#define AST2600_HW_STRAP1_PROT TO_REG(0x508)
|
||||
#define AST2600_HW_STRAP2 TO_REG(0x510)
|
||||
#define AST2600_HW_STRAP2_CLR TO_REG(0x514)
|
||||
#define AST2600_HW_STRAP2_PROT TO_REG(0x518)
|
||||
#define AST2600_RNG_CTRL TO_REG(0x524)
|
||||
#define AST2600_RNG_DATA TO_REG(0x540)
|
||||
|
||||
#define AST2600_CLK TO_REG(0x40)
|
||||
|
||||
#define SCU_IO_REGION_SIZE 0x1000
|
||||
|
||||
static const uint32_t ast2400_a0_resets[ASPEED_SCU_NR_REGS] = {
|
||||
|
@ -178,7 +208,7 @@ static uint64_t aspeed_scu_read(void *opaque, hwaddr offset, unsigned size)
|
|||
AspeedSCUState *s = ASPEED_SCU(opaque);
|
||||
int reg = TO_REG(offset);
|
||||
|
||||
if (reg >= ARRAY_SIZE(s->regs)) {
|
||||
if (reg >= ASPEED_SCU_NR_REGS) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
|
@ -208,7 +238,7 @@ static void aspeed_scu_write(void *opaque, hwaddr offset, uint64_t data,
|
|||
AspeedSCUState *s = ASPEED_SCU(opaque);
|
||||
int reg = TO_REG(offset);
|
||||
|
||||
if (reg >= ARRAY_SIZE(s->regs)) {
|
||||
if (reg >= ASPEED_SCU_NR_REGS) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
|
@ -346,7 +376,7 @@ static void aspeed_scu_reset(DeviceState *dev)
|
|||
AspeedSCUState *s = ASPEED_SCU(dev);
|
||||
AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
|
||||
|
||||
memcpy(s->regs, asc->resets, sizeof(s->regs));
|
||||
memcpy(s->regs, asc->resets, asc->nr_regs * 4);
|
||||
s->regs[SILICON_REV] = s->silicon_rev;
|
||||
s->regs[HW_STRAP1] = s->hw_strap1;
|
||||
s->regs[HW_STRAP2] = s->hw_strap2;
|
||||
|
@ -358,6 +388,7 @@ static uint32_t aspeed_silicon_revs[] = {
|
|||
AST2400_A1_SILICON_REV,
|
||||
AST2500_A0_SILICON_REV,
|
||||
AST2500_A1_SILICON_REV,
|
||||
AST2600_A0_SILICON_REV,
|
||||
};
|
||||
|
||||
bool is_supported_silicon_rev(uint32_t silicon_rev)
|
||||
|
@ -377,6 +408,7 @@ static void aspeed_scu_realize(DeviceState *dev, Error **errp)
|
|||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
AspeedSCUState *s = ASPEED_SCU(dev);
|
||||
AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
|
||||
|
||||
if (!is_supported_silicon_rev(s->silicon_rev)) {
|
||||
error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
|
||||
|
@ -384,7 +416,7 @@ static void aspeed_scu_realize(DeviceState *dev, Error **errp)
|
|||
return;
|
||||
}
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_scu_ops, s,
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), asc->ops, s,
|
||||
TYPE_ASPEED_SCU, SCU_IO_REGION_SIZE);
|
||||
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
|
@ -392,10 +424,10 @@ static void aspeed_scu_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
static const VMStateDescription vmstate_aspeed_scu = {
|
||||
.name = "aspeed.scu",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32_ARRAY(regs, AspeedSCUState, ASPEED_SCU_NR_REGS),
|
||||
VMSTATE_UINT32_ARRAY(regs, AspeedSCUState, ASPEED_AST2600_SCU_NR_REGS),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
@ -436,6 +468,8 @@ static void aspeed_2400_scu_class_init(ObjectClass *klass, void *data)
|
|||
asc->resets = ast2400_a0_resets;
|
||||
asc->calc_hpll = aspeed_2400_scu_calc_hpll;
|
||||
asc->apb_divider = 2;
|
||||
asc->nr_regs = ASPEED_SCU_NR_REGS;
|
||||
asc->ops = &aspeed_scu_ops;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2400_scu_info = {
|
||||
|
@ -454,6 +488,8 @@ static void aspeed_2500_scu_class_init(ObjectClass *klass, void *data)
|
|||
asc->resets = ast2500_a1_resets;
|
||||
asc->calc_hpll = aspeed_2500_scu_calc_hpll;
|
||||
asc->apb_divider = 4;
|
||||
asc->nr_regs = ASPEED_SCU_NR_REGS;
|
||||
asc->ops = &aspeed_scu_ops;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2500_scu_info = {
|
||||
|
@ -463,11 +499,155 @@ static const TypeInfo aspeed_2500_scu_info = {
|
|||
.class_init = aspeed_2500_scu_class_init,
|
||||
};
|
||||
|
||||
static uint64_t aspeed_ast2600_scu_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
AspeedSCUState *s = ASPEED_SCU(opaque);
|
||||
int reg = TO_REG(offset);
|
||||
|
||||
if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (reg) {
|
||||
case AST2600_HPLL_EXT:
|
||||
case AST2600_EPLL_EXT:
|
||||
case AST2600_MPLL_EXT:
|
||||
/* PLLs are always "locked" */
|
||||
return s->regs[reg] | BIT(31);
|
||||
case AST2600_RNG_DATA:
|
||||
/*
|
||||
* On hardware, RNG_DATA works regardless of the state of the
|
||||
* enable bit in RNG_CTRL
|
||||
*
|
||||
* TODO: Check this is true for ast2600
|
||||
*/
|
||||
s->regs[AST2600_RNG_DATA] = aspeed_scu_get_random();
|
||||
break;
|
||||
}
|
||||
|
||||
return s->regs[reg];
|
||||
}
|
||||
|
||||
static void aspeed_ast2600_scu_write(void *opaque, hwaddr offset, uint64_t data,
|
||||
unsigned size)
|
||||
{
|
||||
AspeedSCUState *s = ASPEED_SCU(opaque);
|
||||
int reg = TO_REG(offset);
|
||||
|
||||
if (reg >= ASPEED_AST2600_SCU_NR_REGS) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Out-of-bounds write at offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
if (reg > PROT_KEY && !s->regs[PROT_KEY]) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: SCU is locked!\n", __func__);
|
||||
}
|
||||
|
||||
trace_aspeed_scu_write(offset, size, data);
|
||||
|
||||
switch (reg) {
|
||||
case AST2600_PROT_KEY:
|
||||
s->regs[reg] = (data == ASPEED_SCU_PROT_KEY) ? 1 : 0;
|
||||
return;
|
||||
case AST2600_HW_STRAP1:
|
||||
case AST2600_HW_STRAP2:
|
||||
if (s->regs[reg + 2]) {
|
||||
return;
|
||||
}
|
||||
/* fall through */
|
||||
case AST2600_SYS_RST_CTRL:
|
||||
case AST2600_SYS_RST_CTRL2:
|
||||
/* W1S (Write 1 to set) registers */
|
||||
s->regs[reg] |= data;
|
||||
return;
|
||||
case AST2600_SYS_RST_CTRL_CLR:
|
||||
case AST2600_SYS_RST_CTRL2_CLR:
|
||||
case AST2600_HW_STRAP1_CLR:
|
||||
case AST2600_HW_STRAP2_CLR:
|
||||
/* W1C (Write 1 to clear) registers */
|
||||
s->regs[reg] &= ~data;
|
||||
return;
|
||||
|
||||
case AST2600_RNG_DATA:
|
||||
case AST2600_SILICON_REV:
|
||||
case AST2600_SILICON_REV2:
|
||||
/* Add read only registers here */
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Write to read-only offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
return;
|
||||
}
|
||||
|
||||
s->regs[reg] = data;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps aspeed_ast2600_scu_ops = {
|
||||
.read = aspeed_ast2600_scu_read,
|
||||
.write = aspeed_ast2600_scu_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.valid.min_access_size = 4,
|
||||
.valid.max_access_size = 4,
|
||||
.valid.unaligned = false,
|
||||
};
|
||||
|
||||
static const uint32_t ast2600_a0_resets[ASPEED_AST2600_SCU_NR_REGS] = {
|
||||
[AST2600_SILICON_REV] = AST2600_SILICON_REV,
|
||||
[AST2600_SILICON_REV2] = AST2600_SILICON_REV,
|
||||
[AST2600_SYS_RST_CTRL] = 0xF7CFFEDC | 0x100,
|
||||
[AST2600_SYS_RST_CTRL2] = 0xFFFFFFFC,
|
||||
[AST2600_CLK_STOP_CTRL] = 0xEFF43E8B,
|
||||
[AST2600_CLK_STOP_CTRL2] = 0xFFF0FFF0,
|
||||
[AST2600_SDRAM_HANDSHAKE] = 0x00000040, /* SoC completed DRAM init */
|
||||
[AST2600_HPLL_PARAM] = 0x1000405F,
|
||||
};
|
||||
|
||||
static void aspeed_ast2600_scu_reset(DeviceState *dev)
|
||||
{
|
||||
AspeedSCUState *s = ASPEED_SCU(dev);
|
||||
AspeedSCUClass *asc = ASPEED_SCU_GET_CLASS(dev);
|
||||
|
||||
memcpy(s->regs, asc->resets, asc->nr_regs * 4);
|
||||
|
||||
s->regs[AST2600_SILICON_REV] = s->silicon_rev;
|
||||
s->regs[AST2600_SILICON_REV2] = s->silicon_rev;
|
||||
s->regs[AST2600_HW_STRAP1] = s->hw_strap1;
|
||||
s->regs[AST2600_HW_STRAP2] = s->hw_strap2;
|
||||
s->regs[PROT_KEY] = s->hw_prot_key;
|
||||
}
|
||||
|
||||
static void aspeed_2600_scu_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedSCUClass *asc = ASPEED_SCU_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2600 System Control Unit";
|
||||
dc->reset = aspeed_ast2600_scu_reset;
|
||||
asc->resets = ast2600_a0_resets;
|
||||
asc->calc_hpll = aspeed_2500_scu_calc_hpll; /* No change since AST2500 */
|
||||
asc->apb_divider = 4;
|
||||
asc->nr_regs = ASPEED_AST2600_SCU_NR_REGS;
|
||||
asc->ops = &aspeed_ast2600_scu_ops;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2600_scu_info = {
|
||||
.name = TYPE_ASPEED_2600_SCU,
|
||||
.parent = TYPE_ASPEED_SCU,
|
||||
.instance_size = sizeof(AspeedSCUState),
|
||||
.class_init = aspeed_2600_scu_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_scu_register_types(void)
|
||||
{
|
||||
type_register_static(&aspeed_scu_info);
|
||||
type_register_static(&aspeed_2400_scu_info);
|
||||
type_register_static(&aspeed_2500_scu_info);
|
||||
type_register_static(&aspeed_2600_scu_info);
|
||||
}
|
||||
|
||||
type_init(aspeed_scu_register_types);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
/* Control/Status Register #1 (ast2500) */
|
||||
#define R_STATUS1 (0x60 / 4)
|
||||
#define PHY_BUSY_STATE BIT(0)
|
||||
#define PHY_PLL_LOCK_STATUS BIT(4)
|
||||
|
||||
#define R_ECC_TEST_CTRL (0x70 / 4)
|
||||
#define ECC_TEST_FINISHED BIT(12)
|
||||
|
@ -85,6 +86,11 @@
|
|||
#define ASPEED_SDMC_AST2500_512MB 0x2
|
||||
#define ASPEED_SDMC_AST2500_1024MB 0x3
|
||||
|
||||
#define ASPEED_SDMC_AST2600_256MB 0x0
|
||||
#define ASPEED_SDMC_AST2600_512MB 0x1
|
||||
#define ASPEED_SDMC_AST2600_1024MB 0x2
|
||||
#define ASPEED_SDMC_AST2600_2048MB 0x3
|
||||
|
||||
#define ASPEED_SDMC_AST2500_READONLY_MASK \
|
||||
(ASPEED_SDMC_HW_VERSION(0xf) | ASPEED_SDMC_CACHE_INITIAL_DONE | \
|
||||
ASPEED_SDMC_AST2500_RESERVED | ASPEED_SDMC_VGA_COMPAT | \
|
||||
|
@ -110,6 +116,7 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
|
|||
unsigned int size)
|
||||
{
|
||||
AspeedSDMCState *s = ASPEED_SDMC(opaque);
|
||||
AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
|
||||
|
||||
addr >>= 2;
|
||||
|
||||
|
@ -130,41 +137,7 @@ static void aspeed_sdmc_write(void *opaque, hwaddr addr, uint64_t data,
|
|||
return;
|
||||
}
|
||||
|
||||
if (addr == R_CONF) {
|
||||
/* Make sure readonly bits are kept */
|
||||
switch (s->silicon_rev) {
|
||||
case AST2400_A0_SILICON_REV:
|
||||
case AST2400_A1_SILICON_REV:
|
||||
data &= ~ASPEED_SDMC_READONLY_MASK;
|
||||
data |= s->fixed_conf;
|
||||
break;
|
||||
case AST2500_A0_SILICON_REV:
|
||||
case AST2500_A1_SILICON_REV:
|
||||
data &= ~ASPEED_SDMC_AST2500_READONLY_MASK;
|
||||
data |= s->fixed_conf;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
if (s->silicon_rev == AST2500_A0_SILICON_REV ||
|
||||
s->silicon_rev == AST2500_A1_SILICON_REV) {
|
||||
switch (addr) {
|
||||
case R_STATUS1:
|
||||
/* Will never return 'busy' */
|
||||
data &= ~PHY_BUSY_STATE;
|
||||
break;
|
||||
case R_ECC_TEST_CTRL:
|
||||
/* Always done, always happy */
|
||||
data |= ECC_TEST_FINISHED;
|
||||
data &= ~ECC_TEST_FAIL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s->regs[addr] = data;
|
||||
asc->write(s, addr, data);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps aspeed_sdmc_ops = {
|
||||
|
@ -219,47 +192,46 @@ static int ast2500_rambits(AspeedSDMCState *s)
|
|||
return ASPEED_SDMC_AST2500_512MB;
|
||||
}
|
||||
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
||||
/* use a common default */
|
||||
warn_report("Invalid RAM size 0x%" PRIx64 ". Using default 512M",
|
||||
s->ram_size);
|
||||
s->ram_size = 512 << 20;
|
||||
return ASPEED_SDMC_AST2600_512MB;
|
||||
}
|
||||
|
||||
static void aspeed_sdmc_reset(DeviceState *dev)
|
||||
{
|
||||
AspeedSDMCState *s = ASPEED_SDMC(dev);
|
||||
AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
|
||||
|
||||
memset(s->regs, 0, sizeof(s->regs));
|
||||
|
||||
/* Set ram size bit and defaults values */
|
||||
s->regs[R_CONF] = s->fixed_conf;
|
||||
s->regs[R_CONF] = asc->compute_conf(s, 0);
|
||||
}
|
||||
|
||||
static void aspeed_sdmc_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
AspeedSDMCState *s = ASPEED_SDMC(dev);
|
||||
AspeedSDMCClass *asc = ASPEED_SDMC_GET_CLASS(s);
|
||||
|
||||
if (!is_supported_silicon_rev(s->silicon_rev)) {
|
||||
error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
|
||||
s->silicon_rev);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (s->silicon_rev) {
|
||||
case AST2400_A0_SILICON_REV:
|
||||
case AST2400_A1_SILICON_REV:
|
||||
s->ram_bits = ast2400_rambits(s);
|
||||
s->max_ram_size = 512 << 20;
|
||||
s->fixed_conf = ASPEED_SDMC_VGA_COMPAT |
|
||||
ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
|
||||
break;
|
||||
case AST2500_A0_SILICON_REV:
|
||||
case AST2500_A1_SILICON_REV:
|
||||
s->ram_bits = ast2500_rambits(s);
|
||||
s->max_ram_size = 1024 << 20;
|
||||
s->fixed_conf = ASPEED_SDMC_HW_VERSION(1) |
|
||||
ASPEED_SDMC_VGA_APERTURE(ASPEED_SDMC_VGA_64MB) |
|
||||
ASPEED_SDMC_CACHE_INITIAL_DONE |
|
||||
ASPEED_SDMC_DRAM_SIZE(s->ram_bits);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
s->max_ram_size = asc->max_ram_size;
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_sdmc_ops, s,
|
||||
TYPE_ASPEED_SDMC, 0x1000);
|
||||
|
@ -277,7 +249,6 @@ static const VMStateDescription vmstate_aspeed_sdmc = {
|
|||
};
|
||||
|
||||
static Property aspeed_sdmc_properties[] = {
|
||||
DEFINE_PROP_UINT32("silicon-rev", AspeedSDMCState, silicon_rev, 0),
|
||||
DEFINE_PROP_UINT64("ram-size", AspeedSDMCState, ram_size, 0),
|
||||
DEFINE_PROP_UINT64("max-ram-size", AspeedSDMCState, max_ram_size, 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
|
@ -298,11 +269,164 @@ static const TypeInfo aspeed_sdmc_info = {
|
|||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(AspeedSDMCState),
|
||||
.class_init = aspeed_sdmc_class_init,
|
||||
.class_size = sizeof(AspeedSDMCClass),
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
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));
|
||||
|
||||
/* Make sure readonly bits are kept */
|
||||
data &= ~ASPEED_SDMC_READONLY_MASK;
|
||||
|
||||
return data | fixed_conf;
|
||||
}
|
||||
|
||||
static void aspeed_2400_sdmc_write(AspeedSDMCState *s, uint32_t reg,
|
||||
uint32_t data)
|
||||
{
|
||||
switch (reg) {
|
||||
case R_CONF:
|
||||
data = aspeed_2400_sdmc_compute_conf(s, data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
s->regs[reg] = data;
|
||||
}
|
||||
|
||||
static void aspeed_2400_sdmc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2400 SDRAM Memory Controller";
|
||||
asc->max_ram_size = 512 << 20;
|
||||
asc->compute_conf = aspeed_2400_sdmc_compute_conf;
|
||||
asc->write = aspeed_2400_sdmc_write;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2400_sdmc_info = {
|
||||
.name = TYPE_ASPEED_2400_SDMC,
|
||||
.parent = TYPE_ASPEED_SDMC,
|
||||
.class_init = aspeed_2400_sdmc_class_init,
|
||||
};
|
||||
|
||||
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));
|
||||
|
||||
/* Make sure readonly bits are kept */
|
||||
data &= ~ASPEED_SDMC_AST2500_READONLY_MASK;
|
||||
|
||||
return data | fixed_conf;
|
||||
}
|
||||
|
||||
static void aspeed_2500_sdmc_write(AspeedSDMCState *s, uint32_t reg,
|
||||
uint32_t data)
|
||||
{
|
||||
switch (reg) {
|
||||
case R_CONF:
|
||||
data = aspeed_2500_sdmc_compute_conf(s, data);
|
||||
break;
|
||||
case R_STATUS1:
|
||||
/* Will never return 'busy' */
|
||||
data &= ~PHY_BUSY_STATE;
|
||||
break;
|
||||
case R_ECC_TEST_CTRL:
|
||||
/* Always done, always happy */
|
||||
data |= ECC_TEST_FINISHED;
|
||||
data &= ~ECC_TEST_FAIL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
s->regs[reg] = data;
|
||||
}
|
||||
|
||||
static void aspeed_2500_sdmc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2500 SDRAM Memory Controller";
|
||||
asc->max_ram_size = 1024 << 20;
|
||||
asc->compute_conf = aspeed_2500_sdmc_compute_conf;
|
||||
asc->write = aspeed_2500_sdmc_write;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2500_sdmc_info = {
|
||||
.name = TYPE_ASPEED_2500_SDMC,
|
||||
.parent = TYPE_ASPEED_SDMC,
|
||||
.class_init = aspeed_2500_sdmc_class_init,
|
||||
};
|
||||
|
||||
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));
|
||||
|
||||
/* Make sure readonly bits are kept (use ast2500 mask) */
|
||||
data &= ~ASPEED_SDMC_AST2500_READONLY_MASK;
|
||||
|
||||
return data | fixed_conf;
|
||||
}
|
||||
|
||||
static void aspeed_2600_sdmc_write(AspeedSDMCState *s, uint32_t reg,
|
||||
uint32_t data)
|
||||
{
|
||||
switch (reg) {
|
||||
case R_CONF:
|
||||
data = aspeed_2600_sdmc_compute_conf(s, data);
|
||||
break;
|
||||
case R_STATUS1:
|
||||
/* Will never return 'busy'. 'lock status' is always set */
|
||||
data &= ~PHY_BUSY_STATE;
|
||||
data |= PHY_PLL_LOCK_STATUS;
|
||||
break;
|
||||
case R_ECC_TEST_CTRL:
|
||||
/* Always done, always happy */
|
||||
data |= ECC_TEST_FINISHED;
|
||||
data &= ~ECC_TEST_FAIL;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
s->regs[reg] = data;
|
||||
}
|
||||
|
||||
static void aspeed_2600_sdmc_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedSDMCClass *asc = ASPEED_SDMC_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2600 SDRAM Memory Controller";
|
||||
asc->max_ram_size = 2048 << 20;
|
||||
asc->compute_conf = aspeed_2600_sdmc_compute_conf;
|
||||
asc->write = aspeed_2600_sdmc_write;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2600_sdmc_info = {
|
||||
.name = TYPE_ASPEED_2600_SDMC,
|
||||
.parent = TYPE_ASPEED_SDMC,
|
||||
.class_init = aspeed_2600_sdmc_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_sdmc_register_types(void)
|
||||
{
|
||||
type_register_static(&aspeed_sdmc_info);
|
||||
type_register_static(&aspeed_2400_sdmc_info);
|
||||
type_register_static(&aspeed_2500_sdmc_info);
|
||||
type_register_static(&aspeed_2600_sdmc_info);
|
||||
}
|
||||
|
||||
type_init(aspeed_sdmc_register_types);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "migration/vmstate.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/module.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define MAIL0_PEEK 0x90
|
||||
#define MAIL0_SENDER 0x94
|
||||
|
@ -123,6 +124,7 @@ static void bcm2835_mbox_update(BCM2835MboxState *s)
|
|||
set = true;
|
||||
}
|
||||
}
|
||||
trace_bcm2835_mbox_irq(set);
|
||||
qemu_set_irq(s->arm_irq, set);
|
||||
}
|
||||
|
||||
|
@ -176,10 +178,12 @@ static uint64_t bcm2835_mbox_read(void *opaque, hwaddr offset, unsigned size)
|
|||
break;
|
||||
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
trace_bcm2835_mbox_read(size, offset, res);
|
||||
return 0;
|
||||
}
|
||||
trace_bcm2835_mbox_read(size, offset, res);
|
||||
|
||||
bcm2835_mbox_update(s);
|
||||
|
||||
|
@ -195,6 +199,7 @@ static void bcm2835_mbox_write(void *opaque, hwaddr offset,
|
|||
|
||||
offset &= 0xff;
|
||||
|
||||
trace_bcm2835_mbox_write(size, offset, value);
|
||||
switch (offset) {
|
||||
case MAIL0_SENDER:
|
||||
break;
|
||||
|
@ -228,8 +233,9 @@ static void bcm2835_mbox_write(void *opaque, hwaddr offset,
|
|||
break;
|
||||
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n",
|
||||
__func__, offset);
|
||||
qemu_log_mask(LOG_UNIMP, "%s: Unsupported offset 0x%"HWADDR_PRIx
|
||||
" value 0x%"PRIx64"\n",
|
||||
__func__, offset, value);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -310,7 +316,7 @@ static void bcm2835_mbox_realize(DeviceState *dev, Error **errp)
|
|||
}
|
||||
|
||||
s->mbox_mr = MEMORY_REGION(obj);
|
||||
address_space_init(&s->mbox_as, s->mbox_mr, NULL);
|
||||
address_space_init(&s->mbox_as, s->mbox_mr, TYPE_BCM2835_MBOX "-memory");
|
||||
bcm2835_mbox_reset(dev);
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "sysemu/dma.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/module.h"
|
||||
#include "trace.h"
|
||||
|
||||
/* https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */
|
||||
|
||||
|
@ -56,7 +57,8 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
|
|||
break;
|
||||
case 0x00010001: /* Get board model */
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"bcm2835_property: %x get board model NYI\n", tag);
|
||||
"bcm2835_property: 0x%08x get board model NYI\n",
|
||||
tag);
|
||||
resplen = 4;
|
||||
break;
|
||||
case 0x00010002: /* Get board revision */
|
||||
|
@ -69,7 +71,8 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
|
|||
break;
|
||||
case 0x00010004: /* Get board serial */
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"bcm2835_property: %x get board serial NYI\n", tag);
|
||||
"bcm2835_property: 0x%08x get board serial NYI\n",
|
||||
tag);
|
||||
resplen = 8;
|
||||
break;
|
||||
case 0x00010005: /* Get ARM memory */
|
||||
|
@ -104,7 +107,8 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
|
|||
|
||||
case 0x00038001: /* Set clock state */
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"bcm2835_property: %x set clock state NYI\n", tag);
|
||||
"bcm2835_property: 0x%08x set clock state NYI\n",
|
||||
tag);
|
||||
resplen = 8;
|
||||
break;
|
||||
|
||||
|
@ -129,7 +133,8 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
|
|||
case 0x00038004: /* Set max clock rate */
|
||||
case 0x00038007: /* Set min clock rate */
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"bcm2835_property: %x set clock rates NYI\n", tag);
|
||||
"bcm2835_property: 0x%08x set clock rate NYI\n",
|
||||
tag);
|
||||
resplen = 8;
|
||||
break;
|
||||
|
||||
|
@ -274,11 +279,12 @@ static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
|
|||
break;
|
||||
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"bcm2835_property: unhandled tag %08x\n", tag);
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
"bcm2835_property: unhandled tag 0x%08x\n", tag);
|
||||
break;
|
||||
}
|
||||
|
||||
trace_bcm2835_mbox_property(tag, bufsize, resplen);
|
||||
if (tag == 0) {
|
||||
break;
|
||||
}
|
||||
|
@ -403,7 +409,7 @@ static void bcm2835_property_realize(DeviceState *dev, Error **errp)
|
|||
}
|
||||
|
||||
s->dma_mr = MEMORY_REGION(obj);
|
||||
address_space_init(&s->dma_as, s->dma_mr, NULL);
|
||||
address_space_init(&s->dma_as, s->dma_mr, TYPE_BCM2835_PROPERTY "-memory");
|
||||
|
||||
/* TODO: connect to MAC address of USB NIC device, once we emulate it */
|
||||
qemu_macaddr_default_if_unset(&s->macaddr);
|
||||
|
|
|
@ -143,3 +143,9 @@ armsse_mhu_write(uint64_t offset, uint64_t data, unsigned size) "SSE-200 MHU wri
|
|||
|
||||
# aspeed_xdma.c
|
||||
aspeed_xdma_write(uint64_t offset, uint64_t data) "XDMA write: offset 0x%" PRIx64 " data 0x%" PRIx64
|
||||
|
||||
# bcm2835_mbox.c
|
||||
bcm2835_mbox_write(unsigned int size, uint64_t addr, uint64_t value) "mbox write sz:%u addr:0x%"PRIx64" data:0x%"PRIx64
|
||||
bcm2835_mbox_read(unsigned int size, uint64_t addr, uint64_t value) "mbox read sz:%u addr:0x%"PRIx64" data:0x%"PRIx64
|
||||
bcm2835_mbox_irq(unsigned level) "mbox irq:ARM level:%u"
|
||||
bcm2835_mbox_property(uint32_t tag, uint32_t bufsize, size_t resplen) "mbox property tag:0x%08x in_sz:%u out_sz:%zu"
|
||||
|
|
|
@ -393,7 +393,7 @@ static void etsec_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
|
||||
etsec->bh = qemu_bh_new(etsec_timer_hit, etsec);
|
||||
etsec->ptimer = ptimer_init(etsec->bh, PTIMER_POLICY_DEFAULT);
|
||||
etsec->ptimer = ptimer_init_with_bh(etsec->bh, PTIMER_POLICY_DEFAULT);
|
||||
ptimer_set_freq(etsec->ptimer, 100);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "hw/irq.h"
|
||||
#include "hw/net/ftgmac100.h"
|
||||
#include "sysemu/dma.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/module.h"
|
||||
#include "net/checksum.h"
|
||||
|
@ -1087,9 +1088,170 @@ static const TypeInfo ftgmac100_info = {
|
|||
.class_init = ftgmac100_class_init,
|
||||
};
|
||||
|
||||
/*
|
||||
* AST2600 MII controller
|
||||
*/
|
||||
#define ASPEED_MII_PHYCR_FIRE BIT(31)
|
||||
#define ASPEED_MII_PHYCR_ST_22 BIT(28)
|
||||
#define ASPEED_MII_PHYCR_OP(x) ((x) & (ASPEED_MII_PHYCR_OP_WRITE | \
|
||||
ASPEED_MII_PHYCR_OP_READ))
|
||||
#define ASPEED_MII_PHYCR_OP_WRITE BIT(26)
|
||||
#define ASPEED_MII_PHYCR_OP_READ BIT(27)
|
||||
#define ASPEED_MII_PHYCR_DATA(x) (x & 0xffff)
|
||||
#define ASPEED_MII_PHYCR_PHY(x) (((x) >> 21) & 0x1f)
|
||||
#define ASPEED_MII_PHYCR_REG(x) (((x) >> 16) & 0x1f)
|
||||
|
||||
#define ASPEED_MII_PHYDATA_IDLE BIT(16)
|
||||
|
||||
static void aspeed_mii_transition(AspeedMiiState *s, bool fire)
|
||||
{
|
||||
if (fire) {
|
||||
s->phycr |= ASPEED_MII_PHYCR_FIRE;
|
||||
s->phydata &= ~ASPEED_MII_PHYDATA_IDLE;
|
||||
} else {
|
||||
s->phycr &= ~ASPEED_MII_PHYCR_FIRE;
|
||||
s->phydata |= ASPEED_MII_PHYDATA_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
static void aspeed_mii_do_phy_ctl(AspeedMiiState *s)
|
||||
{
|
||||
uint8_t reg;
|
||||
uint16_t data;
|
||||
|
||||
if (!(s->phycr & ASPEED_MII_PHYCR_ST_22)) {
|
||||
aspeed_mii_transition(s, !ASPEED_MII_PHYCR_FIRE);
|
||||
qemu_log_mask(LOG_UNIMP, "%s: unsupported ST code\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Nothing to do */
|
||||
if (!(s->phycr & ASPEED_MII_PHYCR_FIRE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
reg = ASPEED_MII_PHYCR_REG(s->phycr);
|
||||
data = ASPEED_MII_PHYCR_DATA(s->phycr);
|
||||
|
||||
switch (ASPEED_MII_PHYCR_OP(s->phycr)) {
|
||||
case ASPEED_MII_PHYCR_OP_WRITE:
|
||||
do_phy_write(s->nic, reg, data);
|
||||
break;
|
||||
case ASPEED_MII_PHYCR_OP_READ:
|
||||
s->phydata = (s->phydata & ~0xffff) | do_phy_read(s->nic, reg);
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid OP code %08x\n",
|
||||
__func__, s->phycr);
|
||||
}
|
||||
|
||||
aspeed_mii_transition(s, !ASPEED_MII_PHYCR_FIRE);
|
||||
}
|
||||
|
||||
static uint64_t aspeed_mii_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
AspeedMiiState *s = ASPEED_MII(opaque);
|
||||
|
||||
switch (addr) {
|
||||
case 0x0:
|
||||
return s->phycr;
|
||||
case 0x4:
|
||||
return s->phydata;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
static void aspeed_mii_write(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
AspeedMiiState *s = ASPEED_MII(opaque);
|
||||
|
||||
switch (addr) {
|
||||
case 0x0:
|
||||
s->phycr = value & ~(s->phycr & ASPEED_MII_PHYCR_FIRE);
|
||||
break;
|
||||
case 0x4:
|
||||
s->phydata = value & ~(0xffff | ASPEED_MII_PHYDATA_IDLE);
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
aspeed_mii_transition(s, !!(s->phycr & ASPEED_MII_PHYCR_FIRE));
|
||||
aspeed_mii_do_phy_ctl(s);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps aspeed_mii_ops = {
|
||||
.read = aspeed_mii_read,
|
||||
.write = aspeed_mii_write,
|
||||
.valid.min_access_size = 4,
|
||||
.valid.max_access_size = 4,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static void aspeed_mii_reset(DeviceState *dev)
|
||||
{
|
||||
AspeedMiiState *s = ASPEED_MII(dev);
|
||||
|
||||
s->phycr = 0;
|
||||
s->phydata = 0;
|
||||
|
||||
aspeed_mii_transition(s, !!(s->phycr & ASPEED_MII_PHYCR_FIRE));
|
||||
};
|
||||
|
||||
static void aspeed_mii_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
AspeedMiiState *s = ASPEED_MII(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
Object *obj;
|
||||
Error *local_err = NULL;
|
||||
|
||||
obj = object_property_get_link(OBJECT(dev), "nic", &local_err);
|
||||
if (!obj) {
|
||||
error_propagate(errp, local_err);
|
||||
error_prepend(errp, "required link 'nic' not found: ");
|
||||
return;
|
||||
}
|
||||
|
||||
s->nic = FTGMAC100(obj);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(dev), &aspeed_mii_ops, s,
|
||||
TYPE_ASPEED_MII, 0x8);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_aspeed_mii = {
|
||||
.name = TYPE_ASPEED_MII,
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(phycr, FTGMAC100State),
|
||||
VMSTATE_UINT32(phydata, FTGMAC100State),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
static void aspeed_mii_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->vmsd = &vmstate_aspeed_mii;
|
||||
dc->reset = aspeed_mii_reset;
|
||||
dc->realize = aspeed_mii_realize;
|
||||
dc->desc = "Aspeed MII controller";
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_mii_info = {
|
||||
.name = TYPE_ASPEED_MII,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(AspeedMiiState),
|
||||
.class_init = aspeed_mii_class_init,
|
||||
};
|
||||
|
||||
static void ftgmac100_register_types(void)
|
||||
{
|
||||
type_register_static(&ftgmac100_info);
|
||||
type_register_static(&aspeed_mii_info);
|
||||
}
|
||||
|
||||
type_init(ftgmac100_register_types)
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "hw/ptimer.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
/* For crc32 */
|
||||
#include <zlib.h>
|
||||
|
@ -450,8 +449,10 @@ static void lan9118_reset(DeviceState *d)
|
|||
s->e2p_data = 0;
|
||||
s->free_timer_start = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 40;
|
||||
|
||||
ptimer_transaction_begin(s->timer);
|
||||
ptimer_stop(s->timer);
|
||||
ptimer_set_count(s->timer, 0xffff);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
s->gpt_cfg = 0xffff;
|
||||
|
||||
s->mac_cr = MAC_CR_PRMS;
|
||||
|
@ -1100,6 +1101,7 @@ static void lan9118_writel(void *opaque, hwaddr offset,
|
|||
break;
|
||||
case CSR_GPT_CFG:
|
||||
if ((s->gpt_cfg ^ val) & GPT_TIMER_EN) {
|
||||
ptimer_transaction_begin(s->timer);
|
||||
if (val & GPT_TIMER_EN) {
|
||||
ptimer_set_count(s->timer, val & 0xffff);
|
||||
ptimer_run(s->timer, 0);
|
||||
|
@ -1107,6 +1109,7 @@ static void lan9118_writel(void *opaque, hwaddr offset,
|
|||
ptimer_stop(s->timer);
|
||||
ptimer_set_count(s->timer, 0xffff);
|
||||
}
|
||||
ptimer_transaction_commit(s->timer);
|
||||
}
|
||||
s->gpt_cfg = val & (GPT_TIMER_EN | 0xffff);
|
||||
break;
|
||||
|
@ -1328,7 +1331,6 @@ static void lan9118_realize(DeviceState *dev, Error **errp)
|
|||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
lan9118_state *s = LAN9118(dev);
|
||||
QEMUBH *bh;
|
||||
int i;
|
||||
const MemoryRegionOps *mem_ops =
|
||||
s->mode_16bit ? &lan9118_16bit_mem_ops : &lan9118_mem_ops;
|
||||
|
@ -1349,10 +1351,11 @@ static void lan9118_realize(DeviceState *dev, Error **errp)
|
|||
s->pmt_ctrl = 1;
|
||||
s->txp = &s->tx_packet;
|
||||
|
||||
bh = qemu_bh_new(lan9118_tick, s);
|
||||
s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
|
||||
s->timer = ptimer_init(lan9118_tick, s, PTIMER_POLICY_DEFAULT);
|
||||
ptimer_transaction_begin(s->timer);
|
||||
ptimer_set_freq(s->timer, 10000);
|
||||
ptimer_set_limit(s->timer, 0xffff, 1);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
}
|
||||
|
||||
static Property lan9118_properties[] = {
|
||||
|
|
|
@ -8,3 +8,4 @@ obj-$(CONFIG_MILKYMIST) += milkymist-memcard.o
|
|||
obj-$(CONFIG_OMAP) += omap_mmc.o
|
||||
obj-$(CONFIG_PXA2XX) += pxa2xx_mmci.o
|
||||
obj-$(CONFIG_RASPI) += bcm2835_sdhost.o
|
||||
obj-$(CONFIG_ASPEED_SOC) += aspeed_sdhci.o
|
||||
|
|
198
hw/sd/aspeed_sdhci.c
Normal file
198
hw/sd/aspeed_sdhci.c
Normal file
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Aspeed SD Host Controller
|
||||
* Eddie James <eajames@linux.ibm.com>
|
||||
*
|
||||
* Copyright (C) 2019 IBM Corp
|
||||
* SPDX-License-Identifer: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/sd/aspeed_sdhci.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/irq.h"
|
||||
#include "migration/vmstate.h"
|
||||
|
||||
#define ASPEED_SDHCI_INFO 0x00
|
||||
#define ASPEED_SDHCI_INFO_RESET 0x00030000
|
||||
#define ASPEED_SDHCI_DEBOUNCE 0x04
|
||||
#define ASPEED_SDHCI_DEBOUNCE_RESET 0x00000005
|
||||
#define ASPEED_SDHCI_BUS 0x08
|
||||
#define ASPEED_SDHCI_SDIO_140 0x10
|
||||
#define ASPEED_SDHCI_SDIO_148 0x18
|
||||
#define ASPEED_SDHCI_SDIO_240 0x20
|
||||
#define ASPEED_SDHCI_SDIO_248 0x28
|
||||
#define ASPEED_SDHCI_WP_POL 0xec
|
||||
#define ASPEED_SDHCI_CARD_DET 0xf0
|
||||
#define ASPEED_SDHCI_IRQ_STAT 0xfc
|
||||
|
||||
#define TO_REG(addr) ((addr) / sizeof(uint32_t))
|
||||
|
||||
static uint64_t aspeed_sdhci_read(void *opaque, hwaddr addr, unsigned int size)
|
||||
{
|
||||
uint32_t val = 0;
|
||||
AspeedSDHCIState *sdhci = opaque;
|
||||
|
||||
switch (addr) {
|
||||
case ASPEED_SDHCI_SDIO_140:
|
||||
val = (uint32_t)sdhci->slots[0].capareg;
|
||||
break;
|
||||
case ASPEED_SDHCI_SDIO_148:
|
||||
val = (uint32_t)sdhci->slots[0].maxcurr;
|
||||
break;
|
||||
case ASPEED_SDHCI_SDIO_240:
|
||||
val = (uint32_t)sdhci->slots[1].capareg;
|
||||
break;
|
||||
case ASPEED_SDHCI_SDIO_248:
|
||||
val = (uint32_t)sdhci->slots[1].maxcurr;
|
||||
break;
|
||||
default:
|
||||
if (addr < ASPEED_SDHCI_REG_SIZE) {
|
||||
val = sdhci->regs[TO_REG(addr)];
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Out-of-bounds read at 0x%" HWADDR_PRIx "\n",
|
||||
__func__, addr);
|
||||
}
|
||||
}
|
||||
|
||||
return (uint64_t)val;
|
||||
}
|
||||
|
||||
static void aspeed_sdhci_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
unsigned int size)
|
||||
{
|
||||
AspeedSDHCIState *sdhci = opaque;
|
||||
|
||||
switch (addr) {
|
||||
case ASPEED_SDHCI_SDIO_140:
|
||||
sdhci->slots[0].capareg = (uint64_t)(uint32_t)val;
|
||||
break;
|
||||
case ASPEED_SDHCI_SDIO_148:
|
||||
sdhci->slots[0].maxcurr = (uint64_t)(uint32_t)val;
|
||||
break;
|
||||
case ASPEED_SDHCI_SDIO_240:
|
||||
sdhci->slots[1].capareg = (uint64_t)(uint32_t)val;
|
||||
break;
|
||||
case ASPEED_SDHCI_SDIO_248:
|
||||
sdhci->slots[1].maxcurr = (uint64_t)(uint32_t)val;
|
||||
break;
|
||||
default:
|
||||
if (addr < ASPEED_SDHCI_REG_SIZE) {
|
||||
sdhci->regs[TO_REG(addr)] = (uint32_t)val;
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: Out-of-bounds write at 0x%" HWADDR_PRIx "\n",
|
||||
__func__, addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps aspeed_sdhci_ops = {
|
||||
.read = aspeed_sdhci_read,
|
||||
.write = aspeed_sdhci_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid.min_access_size = 4,
|
||||
.valid.max_access_size = 4,
|
||||
};
|
||||
|
||||
static void aspeed_sdhci_set_irq(void *opaque, int n, int level)
|
||||
{
|
||||
AspeedSDHCIState *sdhci = opaque;
|
||||
|
||||
if (level) {
|
||||
sdhci->regs[TO_REG(ASPEED_SDHCI_IRQ_STAT)] |= BIT(n);
|
||||
|
||||
qemu_irq_raise(sdhci->irq);
|
||||
} else {
|
||||
sdhci->regs[TO_REG(ASPEED_SDHCI_IRQ_STAT)] &= ~BIT(n);
|
||||
|
||||
qemu_irq_lower(sdhci->irq);
|
||||
}
|
||||
}
|
||||
|
||||
static void aspeed_sdhci_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
Error *err = NULL;
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
AspeedSDHCIState *sdhci = ASPEED_SDHCI(dev);
|
||||
|
||||
/* Create input irqs for the slots */
|
||||
qdev_init_gpio_in_named_with_opaque(DEVICE(sbd), aspeed_sdhci_set_irq,
|
||||
sdhci, NULL, ASPEED_SDHCI_NUM_SLOTS);
|
||||
|
||||
sysbus_init_irq(sbd, &sdhci->irq);
|
||||
memory_region_init_io(&sdhci->iomem, OBJECT(sdhci), &aspeed_sdhci_ops,
|
||||
sdhci, TYPE_ASPEED_SDHCI, 0x1000);
|
||||
sysbus_init_mmio(sbd, &sdhci->iomem);
|
||||
|
||||
for (int i = 0; i < ASPEED_SDHCI_NUM_SLOTS; ++i) {
|
||||
Object *sdhci_slot = OBJECT(&sdhci->slots[i]);
|
||||
SysBusDevice *sbd_slot = SYS_BUS_DEVICE(&sdhci->slots[i]);
|
||||
|
||||
object_property_set_int(sdhci_slot, 2, "sd-spec-version", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
object_property_set_uint(sdhci_slot, ASPEED_SDHCI_CAPABILITIES,
|
||||
"capareg", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
object_property_set_bool(sdhci_slot, true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
sysbus_connect_irq(sbd_slot, 0, qdev_get_gpio_in(DEVICE(sbd), i));
|
||||
memory_region_add_subregion(&sdhci->iomem, (i + 1) * 0x100,
|
||||
&sdhci->slots[i].iomem);
|
||||
}
|
||||
}
|
||||
|
||||
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_DEBOUNCE)] = ASPEED_SDHCI_DEBOUNCE_RESET;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_aspeed_sdhci = {
|
||||
.name = TYPE_ASPEED_SDHCI,
|
||||
.version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32_ARRAY(regs, AspeedSDHCIState, ASPEED_SDHCI_NUM_REGS),
|
||||
VMSTATE_END_OF_LIST(),
|
||||
},
|
||||
};
|
||||
|
||||
static void aspeed_sdhci_class_init(ObjectClass *classp, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(classp);
|
||||
|
||||
dc->realize = aspeed_sdhci_realize;
|
||||
dc->reset = aspeed_sdhci_reset;
|
||||
dc->vmsd = &vmstate_aspeed_sdhci;
|
||||
}
|
||||
|
||||
static TypeInfo aspeed_sdhci_info = {
|
||||
.name = TYPE_ASPEED_SDHCI,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(AspeedSDHCIState),
|
||||
.class_init = aspeed_sdhci_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_sdhci_register_types(void)
|
||||
{
|
||||
type_register_static(&aspeed_sdhci_info);
|
||||
}
|
||||
|
||||
type_init(aspeed_sdhci_register_types)
|
|
@ -30,6 +30,7 @@
|
|||
#include "qemu/error-report.h"
|
||||
#include "qapi/error.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "qemu/units.h"
|
||||
|
||||
#include "hw/irq.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
|
@ -50,7 +51,7 @@
|
|||
#define CONF_FLASH_TYPE0 0
|
||||
#define CONF_FLASH_TYPE_NOR 0x0
|
||||
#define CONF_FLASH_TYPE_NAND 0x1
|
||||
#define CONF_FLASH_TYPE_SPI 0x2
|
||||
#define CONF_FLASH_TYPE_SPI 0x2 /* AST2600 is SPI only */
|
||||
|
||||
/* CE Control Register */
|
||||
#define R_CE_CTRL (0x04 / 4)
|
||||
|
@ -71,8 +72,11 @@
|
|||
|
||||
/* CEx Control Register */
|
||||
#define R_CTRL0 (0x10 / 4)
|
||||
#define CTRL_IO_QPI (1 << 31)
|
||||
#define CTRL_IO_QUAD_DATA (1 << 30)
|
||||
#define CTRL_IO_DUAL_DATA (1 << 29)
|
||||
#define CTRL_IO_DUAL_ADDR_DATA (1 << 28) /* Includes dummies */
|
||||
#define CTRL_IO_QUAD_ADDR_DATA (1 << 28) /* Includes dummies */
|
||||
#define CTRL_CMD_SHIFT 16
|
||||
#define CTRL_CMD_MASK 0xff
|
||||
#define CTRL_DUMMY_HIGH_SHIFT 14
|
||||
|
@ -136,7 +140,7 @@
|
|||
/* Misc Control Register #2 */
|
||||
#define R_TIMINGS (0x94 / 4)
|
||||
|
||||
/* SPI controller registers and bits */
|
||||
/* SPI controller registers and bits (AST2400) */
|
||||
#define R_SPI_CONF (0x00 / 4)
|
||||
#define SPI_CONF_ENABLE_W0 0
|
||||
#define R_SPI_CTRL0 (0x4 / 4)
|
||||
|
@ -211,6 +215,39 @@ static const AspeedSegments aspeed_segments_ast2500_spi2[] = {
|
|||
{ 0x38000000, 32 * 1024 * 1024 }, /* start address is readonly */
|
||||
{ 0x3A000000, 96 * 1024 * 1024 }, /* end address is readonly */
|
||||
};
|
||||
static uint32_t aspeed_smc_segment_to_reg(const AspeedSMCState *s,
|
||||
const AspeedSegments *seg);
|
||||
static void aspeed_smc_reg_to_segment(const AspeedSMCState *s, uint32_t reg,
|
||||
AspeedSegments *seg);
|
||||
|
||||
/*
|
||||
* AST2600 definitions
|
||||
*/
|
||||
#define ASPEED26_SOC_FMC_FLASH_BASE 0x20000000
|
||||
#define ASPEED26_SOC_SPI_FLASH_BASE 0x30000000
|
||||
#define ASPEED26_SOC_SPI2_FLASH_BASE 0x50000000
|
||||
|
||||
static const AspeedSegments aspeed_segments_ast2600_fmc[] = {
|
||||
{ 0x0, 128 * MiB }, /* start address is readonly */
|
||||
{ 0x0, 0 }, /* disabled */
|
||||
{ 0x0, 0 }, /* disabled */
|
||||
};
|
||||
|
||||
static const AspeedSegments aspeed_segments_ast2600_spi1[] = {
|
||||
{ 0x0, 128 * MiB }, /* start address is readonly */
|
||||
{ 0x0, 0 }, /* disabled */
|
||||
};
|
||||
|
||||
static const AspeedSegments aspeed_segments_ast2600_spi2[] = {
|
||||
{ 0x0, 128 * MiB }, /* start address is readonly */
|
||||
{ 0x0, 0 }, /* disabled */
|
||||
{ 0x0, 0 }, /* disabled */
|
||||
};
|
||||
|
||||
static uint32_t aspeed_2600_smc_segment_to_reg(const AspeedSMCState *s,
|
||||
const AspeedSegments *seg);
|
||||
static void aspeed_2600_smc_reg_to_segment(const AspeedSMCState *s,
|
||||
uint32_t reg, AspeedSegments *seg);
|
||||
|
||||
static const AspeedSMCController controllers[] = {
|
||||
{
|
||||
|
@ -226,6 +263,8 @@ static const AspeedSMCController controllers[] = {
|
|||
.flash_window_size = 0x6000000,
|
||||
.has_dma = false,
|
||||
.nregs = ASPEED_SMC_R_SMC_MAX,
|
||||
.segment_to_reg = aspeed_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_smc_reg_to_segment,
|
||||
}, {
|
||||
.name = "aspeed.fmc-ast2400",
|
||||
.r_conf = R_CONF,
|
||||
|
@ -241,6 +280,8 @@ static const AspeedSMCController controllers[] = {
|
|||
.dma_flash_mask = 0x0FFFFFFC,
|
||||
.dma_dram_mask = 0x1FFFFFFC,
|
||||
.nregs = ASPEED_SMC_R_MAX,
|
||||
.segment_to_reg = aspeed_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_smc_reg_to_segment,
|
||||
}, {
|
||||
.name = "aspeed.spi1-ast2400",
|
||||
.r_conf = R_SPI_CONF,
|
||||
|
@ -254,6 +295,8 @@ static const AspeedSMCController controllers[] = {
|
|||
.flash_window_size = 0x10000000,
|
||||
.has_dma = false,
|
||||
.nregs = ASPEED_SMC_R_SPI_MAX,
|
||||
.segment_to_reg = aspeed_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_smc_reg_to_segment,
|
||||
}, {
|
||||
.name = "aspeed.fmc-ast2500",
|
||||
.r_conf = R_CONF,
|
||||
|
@ -269,6 +312,8 @@ static const AspeedSMCController controllers[] = {
|
|||
.dma_flash_mask = 0x0FFFFFFC,
|
||||
.dma_dram_mask = 0x3FFFFFFC,
|
||||
.nregs = ASPEED_SMC_R_MAX,
|
||||
.segment_to_reg = aspeed_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_smc_reg_to_segment,
|
||||
}, {
|
||||
.name = "aspeed.spi1-ast2500",
|
||||
.r_conf = R_CONF,
|
||||
|
@ -282,6 +327,8 @@ static const AspeedSMCController controllers[] = {
|
|||
.flash_window_size = 0x8000000,
|
||||
.has_dma = false,
|
||||
.nregs = ASPEED_SMC_R_MAX,
|
||||
.segment_to_reg = aspeed_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_smc_reg_to_segment,
|
||||
}, {
|
||||
.name = "aspeed.spi2-ast2500",
|
||||
.r_conf = R_CONF,
|
||||
|
@ -295,19 +342,64 @@ static const AspeedSMCController controllers[] = {
|
|||
.flash_window_size = 0x8000000,
|
||||
.has_dma = false,
|
||||
.nregs = ASPEED_SMC_R_MAX,
|
||||
.segment_to_reg = aspeed_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_smc_reg_to_segment,
|
||||
}, {
|
||||
.name = "aspeed.fmc-ast2600",
|
||||
.r_conf = R_CONF,
|
||||
.r_ce_ctrl = R_CE_CTRL,
|
||||
.r_ctrl0 = R_CTRL0,
|
||||
.r_timings = R_TIMINGS,
|
||||
.conf_enable_w0 = CONF_ENABLE_W0,
|
||||
.max_slaves = 3,
|
||||
.segments = aspeed_segments_ast2600_fmc,
|
||||
.flash_window_base = ASPEED26_SOC_FMC_FLASH_BASE,
|
||||
.flash_window_size = 0x10000000,
|
||||
.has_dma = true,
|
||||
.nregs = ASPEED_SMC_R_MAX,
|
||||
.segment_to_reg = aspeed_2600_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_2600_smc_reg_to_segment,
|
||||
}, {
|
||||
.name = "aspeed.spi1-ast2600",
|
||||
.r_conf = R_CONF,
|
||||
.r_ce_ctrl = R_CE_CTRL,
|
||||
.r_ctrl0 = R_CTRL0,
|
||||
.r_timings = R_TIMINGS,
|
||||
.conf_enable_w0 = CONF_ENABLE_W0,
|
||||
.max_slaves = 2,
|
||||
.segments = aspeed_segments_ast2600_spi1,
|
||||
.flash_window_base = ASPEED26_SOC_SPI_FLASH_BASE,
|
||||
.flash_window_size = 0x10000000,
|
||||
.has_dma = false,
|
||||
.nregs = ASPEED_SMC_R_MAX,
|
||||
.segment_to_reg = aspeed_2600_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_2600_smc_reg_to_segment,
|
||||
}, {
|
||||
.name = "aspeed.spi2-ast2600",
|
||||
.r_conf = R_CONF,
|
||||
.r_ce_ctrl = R_CE_CTRL,
|
||||
.r_ctrl0 = R_CTRL0,
|
||||
.r_timings = R_TIMINGS,
|
||||
.conf_enable_w0 = CONF_ENABLE_W0,
|
||||
.max_slaves = 3,
|
||||
.segments = aspeed_segments_ast2600_spi2,
|
||||
.flash_window_base = ASPEED26_SOC_SPI2_FLASH_BASE,
|
||||
.flash_window_size = 0x10000000,
|
||||
.has_dma = false,
|
||||
.nregs = ASPEED_SMC_R_MAX,
|
||||
.segment_to_reg = aspeed_2600_smc_segment_to_reg,
|
||||
.reg_to_segment = aspeed_2600_smc_reg_to_segment,
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* The Segment Register uses a 8MB unit to encode the start address
|
||||
* and the end address of the mapping window of a flash SPI slave :
|
||||
*
|
||||
* | byte 1 | byte 2 | byte 3 | byte 4 |
|
||||
* +--------+--------+--------+--------+
|
||||
* | end | start | 0 | 0 |
|
||||
*
|
||||
* The Segment Registers of the AST2400 and AST2500 have a 8MB
|
||||
* unit. The address range of a flash SPI slave is encoded with
|
||||
* absolute addresses which should be part of the overall controller
|
||||
* window.
|
||||
*/
|
||||
static inline uint32_t aspeed_smc_segment_to_reg(const AspeedSegments *seg)
|
||||
static uint32_t aspeed_smc_segment_to_reg(const AspeedSMCState *s,
|
||||
const AspeedSegments *seg)
|
||||
{
|
||||
uint32_t reg = 0;
|
||||
reg |= ((seg->addr >> 23) & SEG_START_MASK) << SEG_START_SHIFT;
|
||||
|
@ -315,12 +407,47 @@ static inline uint32_t aspeed_smc_segment_to_reg(const AspeedSegments *seg)
|
|||
return reg;
|
||||
}
|
||||
|
||||
static inline void aspeed_smc_reg_to_segment(uint32_t reg, AspeedSegments *seg)
|
||||
static void aspeed_smc_reg_to_segment(const AspeedSMCState *s,
|
||||
uint32_t reg, AspeedSegments *seg)
|
||||
{
|
||||
seg->addr = ((reg >> SEG_START_SHIFT) & SEG_START_MASK) << 23;
|
||||
seg->size = (((reg >> SEG_END_SHIFT) & SEG_END_MASK) << 23) - seg->addr;
|
||||
}
|
||||
|
||||
/*
|
||||
* The Segment Registers of the AST2600 have a 1MB unit. The address
|
||||
* range of a flash SPI slave is encoded with offsets in the overall
|
||||
* controller window. The previous SoC AST2400 and AST2500 used
|
||||
* absolute addresses. Only bits [27:20] are relevant and the end
|
||||
* address is an upper bound limit.
|
||||
*/
|
||||
#define AST2600_SEG_ADDR_MASK 0x0ff00000
|
||||
|
||||
static uint32_t aspeed_2600_smc_segment_to_reg(const AspeedSMCState *s,
|
||||
const AspeedSegments *seg)
|
||||
{
|
||||
uint32_t reg = 0;
|
||||
|
||||
/* Disabled segments have a nil register */
|
||||
if (!seg->size) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
reg |= (seg->addr & AST2600_SEG_ADDR_MASK) >> 16; /* start offset */
|
||||
reg |= (seg->addr + seg->size - 1) & AST2600_SEG_ADDR_MASK; /* end offset */
|
||||
return reg;
|
||||
}
|
||||
|
||||
static void aspeed_2600_smc_reg_to_segment(const AspeedSMCState *s,
|
||||
uint32_t reg, AspeedSegments *seg)
|
||||
{
|
||||
uint32_t start_offset = (reg << 16) & AST2600_SEG_ADDR_MASK;
|
||||
uint32_t end_offset = reg & AST2600_SEG_ADDR_MASK;
|
||||
|
||||
seg->addr = s->ctrl->flash_window_base + start_offset;
|
||||
seg->size = end_offset + MiB - start_offset;
|
||||
}
|
||||
|
||||
static bool aspeed_smc_flash_overlap(const AspeedSMCState *s,
|
||||
const AspeedSegments *new,
|
||||
int cs)
|
||||
|
@ -333,7 +460,7 @@ static bool aspeed_smc_flash_overlap(const AspeedSMCState *s,
|
|||
continue;
|
||||
}
|
||||
|
||||
aspeed_smc_reg_to_segment(s->regs[R_SEG_ADDR0 + i], &seg);
|
||||
s->ctrl->reg_to_segment(s, s->regs[R_SEG_ADDR0 + i], &seg);
|
||||
|
||||
if (new->addr + new->size > seg.addr &&
|
||||
new->addr < seg.addr + seg.size) {
|
||||
|
@ -354,7 +481,7 @@ static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
|
|||
AspeedSMCFlash *fl = &s->flashes[cs];
|
||||
AspeedSegments seg;
|
||||
|
||||
aspeed_smc_reg_to_segment(new, &seg);
|
||||
s->ctrl->reg_to_segment(s, new, &seg);
|
||||
|
||||
/* The start address of CS0 is read-only */
|
||||
if (cs == 0 && seg.addr != s->ctrl->flash_window_base) {
|
||||
|
@ -362,7 +489,7 @@ static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
|
|||
"%s: Tried to change CS0 start address to 0x%"
|
||||
HWADDR_PRIx "\n", s->ctrl->name, seg.addr);
|
||||
seg.addr = s->ctrl->flash_window_base;
|
||||
new = aspeed_smc_segment_to_reg(&seg);
|
||||
new = s->ctrl->segment_to_reg(s, &seg);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -379,7 +506,7 @@ static void aspeed_smc_flash_set_segment(AspeedSMCState *s, int cs,
|
|||
HWADDR_PRIx "\n", s->ctrl->name, cs, seg.addr + seg.size);
|
||||
seg.size = s->ctrl->segments[cs].addr + s->ctrl->segments[cs].size -
|
||||
seg.addr;
|
||||
new = aspeed_smc_segment_to_reg(&seg);
|
||||
new = s->ctrl->segment_to_reg(s, &seg);
|
||||
}
|
||||
|
||||
/* Keep the segment in the overall flash window */
|
||||
|
@ -455,8 +582,12 @@ static inline int aspeed_smc_flash_cmd(const AspeedSMCFlash *fl)
|
|||
const AspeedSMCState *s = fl->controller;
|
||||
int cmd = (s->regs[s->r_ctrl0 + fl->id] >> CTRL_CMD_SHIFT) & CTRL_CMD_MASK;
|
||||
|
||||
/* In read mode, the default SPI command is READ (0x3). In other
|
||||
* modes, the command should necessarily be defined */
|
||||
/*
|
||||
* In read mode, the default SPI command is READ (0x3). In other
|
||||
* modes, the command should necessarily be defined
|
||||
*
|
||||
* TODO: add support for READ4 (0x13) on AST2600
|
||||
*/
|
||||
if (aspeed_smc_flash_mode(fl) == CTRL_READMODE) {
|
||||
cmd = SPI_OP_READ;
|
||||
}
|
||||
|
@ -509,7 +640,7 @@ static uint32_t aspeed_smc_check_segment_addr(const AspeedSMCFlash *fl,
|
|||
const AspeedSMCState *s = fl->controller;
|
||||
AspeedSegments seg;
|
||||
|
||||
aspeed_smc_reg_to_segment(s->regs[R_SEG_ADDR0 + fl->id], &seg);
|
||||
s->ctrl->reg_to_segment(s, s->regs[R_SEG_ADDR0 + fl->id], &seg);
|
||||
if ((addr % seg.size) != addr) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
"%s: invalid address 0x%08x for CS%d segment : "
|
||||
|
@ -769,7 +900,15 @@ static void aspeed_smc_reset(DeviceState *d)
|
|||
/* setup default segment register values for all */
|
||||
for (i = 0; i < s->ctrl->max_slaves; ++i) {
|
||||
s->regs[R_SEG_ADDR0 + i] =
|
||||
aspeed_smc_segment_to_reg(&s->ctrl->segments[i]);
|
||||
s->ctrl->segment_to_reg(s, &s->ctrl->segments[i]);
|
||||
}
|
||||
|
||||
/* HW strapping flash type for the AST2600 controllers */
|
||||
if (s->ctrl->segments == aspeed_segments_ast2600_fmc) {
|
||||
/* flash type is fixed to SPI for all */
|
||||
s->regs[s->r_conf] |= (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE0);
|
||||
s->regs[s->r_conf] |= (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE1);
|
||||
s->regs[s->r_conf] |= (CONF_FLASH_TYPE_SPI << CONF_FLASH_TYPE2);
|
||||
}
|
||||
|
||||
/* HW strapping flash type for FMC controllers */
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "hw/timer/allwinner-a10-pit.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
|
||||
static void a10_pit_update_irq(AwA10PITState *s)
|
||||
|
@ -80,6 +79,7 @@ static uint64_t a10_pit_read(void *opaque, hwaddr offset, unsigned size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Must be called inside a ptimer transaction block for s->timer[index] */
|
||||
static void a10_pit_set_freq(AwA10PITState *s, int index)
|
||||
{
|
||||
uint32_t prescaler, source, source_freq;
|
||||
|
@ -118,6 +118,7 @@ static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
switch (offset & 0x0f) {
|
||||
case AW_A10_PIT_TIMER_CONTROL:
|
||||
s->control[index] = value;
|
||||
ptimer_transaction_begin(s->timer[index]);
|
||||
a10_pit_set_freq(s, index);
|
||||
if (s->control[index] & AW_A10_PIT_TIMER_RELOAD) {
|
||||
ptimer_set_count(s->timer[index], s->interval[index]);
|
||||
|
@ -131,10 +132,13 @@ static void a10_pit_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
} else {
|
||||
ptimer_stop(s->timer[index]);
|
||||
}
|
||||
ptimer_transaction_commit(s->timer[index]);
|
||||
break;
|
||||
case AW_A10_PIT_TIMER_INTERVAL:
|
||||
s->interval[index] = value;
|
||||
ptimer_transaction_begin(s->timer[index]);
|
||||
ptimer_set_limit(s->timer[index], s->interval[index], 1);
|
||||
ptimer_transaction_commit(s->timer[index]);
|
||||
break;
|
||||
case AW_A10_PIT_TIMER_COUNT:
|
||||
s->count[index] = value;
|
||||
|
@ -225,8 +229,10 @@ static void a10_pit_reset(DeviceState *dev)
|
|||
s->control[i] = AW_A10_PIT_DEFAULT_CLOCK;
|
||||
s->interval[i] = 0;
|
||||
s->count[i] = 0;
|
||||
ptimer_transaction_begin(s->timer[i]);
|
||||
ptimer_stop(s->timer[i]);
|
||||
a10_pit_set_freq(s, i);
|
||||
ptimer_transaction_commit(s->timer[i]);
|
||||
}
|
||||
s->watch_dog_mode = 0;
|
||||
s->watch_dog_control = 0;
|
||||
|
@ -255,7 +261,6 @@ static void a10_pit_init(Object *obj)
|
|||
{
|
||||
AwA10PITState *s = AW_A10_PIT(obj);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
QEMUBH * bh[AW_A10_PIT_TIMER_NR];
|
||||
uint8_t i;
|
||||
|
||||
for (i = 0; i < AW_A10_PIT_TIMER_NR; i++) {
|
||||
|
@ -270,8 +275,7 @@ static void a10_pit_init(Object *obj)
|
|||
|
||||
tc->container = s;
|
||||
tc->index = i;
|
||||
bh[i] = qemu_bh_new(a10_pit_timer_cb, tc);
|
||||
s->timer[i] = ptimer_init(bh[i], PTIMER_POLICY_DEFAULT);
|
||||
s->timer[i] = ptimer_init(a10_pit_timer_cb, tc, PTIMER_POLICY_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -184,7 +184,7 @@ static void altera_timer_realize(DeviceState *dev, Error **errp)
|
|||
}
|
||||
|
||||
t->bh = qemu_bh_new(timer_hit, t);
|
||||
t->ptimer = ptimer_init(t->bh, PTIMER_POLICY_DEFAULT);
|
||||
t->ptimer = ptimer_init_with_bh(t->bh, PTIMER_POLICY_DEFAULT);
|
||||
ptimer_set_freq(t->ptimer, t->freq_hz);
|
||||
|
||||
memory_region_init_io(&t->mmio, OBJECT(t), &timer_ops, t,
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include "hw/timer/arm_mptimer.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
|
@ -65,6 +64,7 @@ static inline uint32_t timerblock_scale(uint32_t control)
|
|||
return (((control >> 8) & 0xff) + 1) * 10;
|
||||
}
|
||||
|
||||
/* Must be called within a ptimer transaction block */
|
||||
static inline void timerblock_set_count(struct ptimer_state *timer,
|
||||
uint32_t control, uint64_t *count)
|
||||
{
|
||||
|
@ -77,6 +77,7 @@ static inline void timerblock_set_count(struct ptimer_state *timer,
|
|||
ptimer_set_count(timer, *count);
|
||||
}
|
||||
|
||||
/* Must be called within a ptimer transaction block */
|
||||
static inline void timerblock_run(struct ptimer_state *timer,
|
||||
uint32_t control, uint32_t load)
|
||||
{
|
||||
|
@ -124,6 +125,7 @@ static void timerblock_write(void *opaque, hwaddr addr,
|
|||
uint32_t control = tb->control;
|
||||
switch (addr) {
|
||||
case 0: /* Load */
|
||||
ptimer_transaction_begin(tb->timer);
|
||||
/* Setting load to 0 stops the timer without doing the tick if
|
||||
* prescaler = 0.
|
||||
*/
|
||||
|
@ -132,8 +134,10 @@ static void timerblock_write(void *opaque, hwaddr addr,
|
|||
}
|
||||
ptimer_set_limit(tb->timer, value, 1);
|
||||
timerblock_run(tb->timer, control, value);
|
||||
ptimer_transaction_commit(tb->timer);
|
||||
break;
|
||||
case 4: /* Counter. */
|
||||
ptimer_transaction_begin(tb->timer);
|
||||
/* Setting counter to 0 stops the one-shot timer, or periodic with
|
||||
* load = 0, without doing the tick if prescaler = 0.
|
||||
*/
|
||||
|
@ -143,8 +147,10 @@ static void timerblock_write(void *opaque, hwaddr addr,
|
|||
}
|
||||
timerblock_set_count(tb->timer, control, &value);
|
||||
timerblock_run(tb->timer, control, value);
|
||||
ptimer_transaction_commit(tb->timer);
|
||||
break;
|
||||
case 8: /* Control. */
|
||||
ptimer_transaction_begin(tb->timer);
|
||||
if ((control & 3) != (value & 3)) {
|
||||
ptimer_stop(tb->timer);
|
||||
}
|
||||
|
@ -160,6 +166,7 @@ static void timerblock_write(void *opaque, hwaddr addr,
|
|||
timerblock_run(tb->timer, value, count);
|
||||
}
|
||||
tb->control = value;
|
||||
ptimer_transaction_commit(tb->timer);
|
||||
break;
|
||||
case 12: /* Interrupt status. */
|
||||
tb->status &= ~value;
|
||||
|
@ -212,9 +219,11 @@ static void timerblock_reset(TimerBlock *tb)
|
|||
tb->control = 0;
|
||||
tb->status = 0;
|
||||
if (tb->timer) {
|
||||
ptimer_transaction_begin(tb->timer);
|
||||
ptimer_stop(tb->timer);
|
||||
ptimer_set_limit(tb->timer, 0, 1);
|
||||
ptimer_set_period(tb->timer, timerblock_scale(0));
|
||||
ptimer_transaction_commit(tb->timer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -228,7 +237,7 @@ static void arm_mptimer_reset(DeviceState *dev)
|
|||
}
|
||||
}
|
||||
|
||||
static void arm_mptimer_init(Object *obj)
|
||||
static void arm_mptimer_init_with_bh(Object *obj)
|
||||
{
|
||||
ARMMPTimerState *s = ARM_MPTIMER(obj);
|
||||
|
||||
|
@ -260,8 +269,7 @@ static void arm_mptimer_realize(DeviceState *dev, Error **errp)
|
|||
*/
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
TimerBlock *tb = &s->timerblock[i];
|
||||
QEMUBH *bh = qemu_bh_new(timerblock_tick, tb);
|
||||
tb->timer = ptimer_init(bh, PTIMER_POLICY);
|
||||
tb->timer = ptimer_init(timerblock_tick, tb, PTIMER_POLICY);
|
||||
sysbus_init_irq(sbd, &tb->irq);
|
||||
memory_region_init_io(&tb->iomem, OBJECT(s), &timerblock_ops, tb,
|
||||
"arm_mptimer_timerblock", 0x20);
|
||||
|
@ -311,7 +319,7 @@ static const TypeInfo arm_mptimer_info = {
|
|||
.name = TYPE_ARM_MPTIMER,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(ARMMPTimerState),
|
||||
.instance_init = arm_mptimer_init,
|
||||
.instance_init = arm_mptimer_init_with_bh,
|
||||
.class_init = arm_mptimer_class_init,
|
||||
};
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "hw/irq.h"
|
||||
#include "hw/ptimer.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
|
@ -75,7 +74,10 @@ static uint32_t arm_timer_read(void *opaque, hwaddr offset)
|
|||
}
|
||||
}
|
||||
|
||||
/* Reset the timer limit after settings have changed. */
|
||||
/*
|
||||
* Reset the timer limit after settings have changed.
|
||||
* May only be called from inside a ptimer transaction block.
|
||||
*/
|
||||
static void arm_timer_recalibrate(arm_timer_state *s, int reload)
|
||||
{
|
||||
uint32_t limit;
|
||||
|
@ -102,13 +104,16 @@ static void arm_timer_write(void *opaque, hwaddr offset,
|
|||
switch (offset >> 2) {
|
||||
case 0: /* TimerLoad */
|
||||
s->limit = value;
|
||||
ptimer_transaction_begin(s->timer);
|
||||
arm_timer_recalibrate(s, 1);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
break;
|
||||
case 1: /* TimerValue */
|
||||
/* ??? Linux seems to want to write to this readonly register.
|
||||
Ignore it. */
|
||||
break;
|
||||
case 2: /* TimerControl */
|
||||
ptimer_transaction_begin(s->timer);
|
||||
if (s->control & TIMER_CTRL_ENABLE) {
|
||||
/* Pause the timer if it is running. This may cause some
|
||||
inaccuracy dure to rounding, but avoids a whole lot of other
|
||||
|
@ -128,13 +133,16 @@ static void arm_timer_write(void *opaque, hwaddr offset,
|
|||
/* Restart the timer if still enabled. */
|
||||
ptimer_run(s->timer, (s->control & TIMER_CTRL_ONESHOT) != 0);
|
||||
}
|
||||
ptimer_transaction_commit(s->timer);
|
||||
break;
|
||||
case 3: /* TimerIntClr */
|
||||
s->int_level = 0;
|
||||
break;
|
||||
case 6: /* TimerBGLoad */
|
||||
s->limit = value;
|
||||
ptimer_transaction_begin(s->timer);
|
||||
arm_timer_recalibrate(s, 0);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR,
|
||||
|
@ -166,14 +174,12 @@ static const VMStateDescription vmstate_arm_timer = {
|
|||
static arm_timer_state *arm_timer_init(uint32_t freq)
|
||||
{
|
||||
arm_timer_state *s;
|
||||
QEMUBH *bh;
|
||||
|
||||
s = (arm_timer_state *)g_malloc0(sizeof(arm_timer_state));
|
||||
s->freq = freq;
|
||||
s->control = TIMER_CTRL_IE;
|
||||
|
||||
bh = qemu_bh_new(arm_timer_tick, s);
|
||||
s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
|
||||
s->timer = ptimer_init(arm_timer_tick, s, PTIMER_POLICY_DEFAULT);
|
||||
vmstate_register(NULL, -1, &vmstate_arm_timer, s);
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -160,7 +160,9 @@ static uint64_t calculate_next(struct AspeedTimer *t)
|
|||
timer_del(&t->timer);
|
||||
|
||||
if (timer_overflow_interrupt(t)) {
|
||||
AspeedTimerCtrlState *s = timer_to_ctrl(t);
|
||||
t->level = !t->level;
|
||||
s->irq_sts |= BIT(t->id);
|
||||
qemu_set_irq(t->irq, t->level);
|
||||
}
|
||||
|
||||
|
@ -199,7 +201,9 @@ static void aspeed_timer_expire(void *opaque)
|
|||
}
|
||||
|
||||
if (interrupt) {
|
||||
AspeedTimerCtrlState *s = timer_to_ctrl(t);
|
||||
t->level = !t->level;
|
||||
s->irq_sts |= BIT(t->id);
|
||||
qemu_set_irq(t->irq, t->level);
|
||||
}
|
||||
|
||||
|
@ -244,22 +248,14 @@ static uint64_t aspeed_timer_read(void *opaque, hwaddr offset, unsigned size)
|
|||
case 0x30: /* Control Register */
|
||||
value = s->ctrl;
|
||||
break;
|
||||
case 0x34: /* Control Register 2 */
|
||||
value = s->ctrl2;
|
||||
break;
|
||||
case 0x00 ... 0x2c: /* Timers 1 - 4 */
|
||||
value = aspeed_timer_get_value(&s->timers[(offset >> 4)], reg);
|
||||
break;
|
||||
case 0x40 ... 0x8c: /* Timers 5 - 8 */
|
||||
value = aspeed_timer_get_value(&s->timers[(offset >> 4) - 1], reg);
|
||||
break;
|
||||
/* Illegal */
|
||||
case 0x38:
|
||||
case 0x3C:
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
value = 0;
|
||||
value = ASPEED_TIMER_GET_CLASS(s)->read(s, offset);
|
||||
break;
|
||||
}
|
||||
trace_aspeed_timer_read(offset, size, value);
|
||||
|
@ -443,9 +439,6 @@ static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
case 0x30:
|
||||
aspeed_timer_set_ctrl(s, tv);
|
||||
break;
|
||||
case 0x34:
|
||||
aspeed_timer_set_ctrl2(s, tv);
|
||||
break;
|
||||
/* Timer Registers */
|
||||
case 0x00 ... 0x2c:
|
||||
aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS), reg, tv);
|
||||
|
@ -453,12 +446,8 @@ static void aspeed_timer_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
case 0x40 ... 0x8c:
|
||||
aspeed_timer_set_value(s, (offset >> TIMER_NR_REGS) - 1, reg, tv);
|
||||
break;
|
||||
/* Illegal */
|
||||
case 0x38:
|
||||
case 0x3C:
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
ASPEED_TIMER_GET_CLASS(s)->write(s, offset, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -472,6 +461,135 @@ static const MemoryRegionOps aspeed_timer_ops = {
|
|||
.valid.unaligned = false,
|
||||
};
|
||||
|
||||
static uint64_t aspeed_2400_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
|
||||
{
|
||||
uint64_t value;
|
||||
|
||||
switch (offset) {
|
||||
case 0x34:
|
||||
value = s->ctrl2;
|
||||
break;
|
||||
case 0x38:
|
||||
case 0x3C:
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static void aspeed_2400_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
|
||||
uint64_t value)
|
||||
{
|
||||
const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
|
||||
|
||||
switch (offset) {
|
||||
case 0x34:
|
||||
aspeed_timer_set_ctrl2(s, tv);
|
||||
break;
|
||||
case 0x38:
|
||||
case 0x3C:
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t aspeed_2500_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
|
||||
{
|
||||
uint64_t value;
|
||||
|
||||
switch (offset) {
|
||||
case 0x34:
|
||||
value = s->ctrl2;
|
||||
break;
|
||||
case 0x38:
|
||||
value = s->ctrl3 & BIT(0);
|
||||
break;
|
||||
case 0x3C:
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static void aspeed_2500_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
|
||||
uint64_t value)
|
||||
{
|
||||
const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
|
||||
uint8_t command;
|
||||
|
||||
switch (offset) {
|
||||
case 0x34:
|
||||
aspeed_timer_set_ctrl2(s, tv);
|
||||
break;
|
||||
case 0x38:
|
||||
command = (value >> 1) & 0xFF;
|
||||
if (command == 0xAE) {
|
||||
s->ctrl3 = 0x1;
|
||||
} else if (command == 0xEA) {
|
||||
s->ctrl3 = 0x0;
|
||||
}
|
||||
break;
|
||||
case 0x3C:
|
||||
if (s->ctrl3 & BIT(0)) {
|
||||
aspeed_timer_set_ctrl(s, s->ctrl & ~tv);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t aspeed_2600_timer_read(AspeedTimerCtrlState *s, hwaddr offset)
|
||||
{
|
||||
uint64_t value;
|
||||
|
||||
switch (offset) {
|
||||
case 0x34:
|
||||
value = s->irq_sts;
|
||||
break;
|
||||
case 0x38:
|
||||
case 0x3C:
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
value = 0;
|
||||
break;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static void aspeed_2600_timer_write(AspeedTimerCtrlState *s, hwaddr offset,
|
||||
uint64_t value)
|
||||
{
|
||||
const uint32_t tv = (uint32_t)(value & 0xFFFFFFFF);
|
||||
|
||||
switch (offset) {
|
||||
case 0x34:
|
||||
s->irq_sts &= tv;
|
||||
break;
|
||||
case 0x3C:
|
||||
aspeed_timer_set_ctrl(s, s->ctrl & ~tv);
|
||||
break;
|
||||
|
||||
case 0x38:
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset 0x%" HWADDR_PRIx "\n",
|
||||
__func__, offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void aspeed_init_one_timer(AspeedTimerCtrlState *s, uint8_t id)
|
||||
{
|
||||
AspeedTimer *t = &s->timers[id];
|
||||
|
@ -525,6 +643,8 @@ static void aspeed_timer_reset(DeviceState *dev)
|
|||
}
|
||||
s->ctrl = 0;
|
||||
s->ctrl2 = 0;
|
||||
s->ctrl3 = 0;
|
||||
s->irq_sts = 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_aspeed_timer = {
|
||||
|
@ -543,11 +663,13 @@ static const VMStateDescription vmstate_aspeed_timer = {
|
|||
|
||||
static const VMStateDescription vmstate_aspeed_timer_state = {
|
||||
.name = "aspeed.timerctrl",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(ctrl, AspeedTimerCtrlState),
|
||||
VMSTATE_UINT32(ctrl2, AspeedTimerCtrlState),
|
||||
VMSTATE_UINT32(ctrl3, AspeedTimerCtrlState),
|
||||
VMSTATE_UINT32(irq_sts, AspeedTimerCtrlState),
|
||||
VMSTATE_STRUCT_ARRAY(timers, AspeedTimerCtrlState,
|
||||
ASPEED_TIMER_NR_TIMERS, 1, vmstate_aspeed_timer,
|
||||
AspeedTimer),
|
||||
|
@ -570,11 +692,64 @@ static const TypeInfo aspeed_timer_info = {
|
|||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(AspeedTimerCtrlState),
|
||||
.class_init = timer_class_init,
|
||||
.class_size = sizeof(AspeedTimerClass),
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void aspeed_2400_timer_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2400 Timer";
|
||||
awc->read = aspeed_2400_timer_read;
|
||||
awc->write = aspeed_2400_timer_write;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2400_timer_info = {
|
||||
.name = TYPE_ASPEED_2400_TIMER,
|
||||
.parent = TYPE_ASPEED_TIMER,
|
||||
.class_init = aspeed_2400_timer_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_2500_timer_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2500 Timer";
|
||||
awc->read = aspeed_2500_timer_read;
|
||||
awc->write = aspeed_2500_timer_write;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2500_timer_info = {
|
||||
.name = TYPE_ASPEED_2500_TIMER,
|
||||
.parent = TYPE_ASPEED_TIMER,
|
||||
.class_init = aspeed_2500_timer_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_2600_timer_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedTimerClass *awc = ASPEED_TIMER_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2600 Timer";
|
||||
awc->read = aspeed_2600_timer_read;
|
||||
awc->write = aspeed_2600_timer_write;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2600_timer_info = {
|
||||
.name = TYPE_ASPEED_2600_TIMER,
|
||||
.parent = TYPE_ASPEED_TIMER,
|
||||
.class_init = aspeed_2600_timer_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_timer_register_types(void)
|
||||
{
|
||||
type_register_static(&aspeed_timer_info);
|
||||
type_register_static(&aspeed_2400_timer_info);
|
||||
type_register_static(&aspeed_2500_timer_info);
|
||||
type_register_static(&aspeed_2600_timer_info);
|
||||
}
|
||||
|
||||
type_init(aspeed_timer_register_types)
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "qemu/log.h"
|
||||
#include "trace.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/irq.h"
|
||||
|
@ -112,6 +111,8 @@ static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
|
|||
/* Handle a write to the CONTROL register */
|
||||
uint32_t changed;
|
||||
|
||||
ptimer_transaction_begin(m->timer);
|
||||
|
||||
newctrl &= R_CONTROL_VALID_MASK;
|
||||
|
||||
changed = m->control ^ newctrl;
|
||||
|
@ -213,6 +214,8 @@ static void cmsdk_dualtimermod_write_control(CMSDKAPBDualTimerModule *m,
|
|||
}
|
||||
|
||||
m->control = newctrl;
|
||||
|
||||
ptimer_transaction_commit(m->timer);
|
||||
}
|
||||
|
||||
static uint64_t cmsdk_apb_dualtimer_read(void *opaque, hwaddr offset,
|
||||
|
@ -330,6 +333,7 @@ static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset,
|
|||
if (!(m->control & R_CONTROL_SIZE_MASK)) {
|
||||
value &= 0xffff;
|
||||
}
|
||||
ptimer_transaction_begin(m->timer);
|
||||
if (!(m->control & R_CONTROL_MODE_MASK)) {
|
||||
/*
|
||||
* In free-running mode this won't set the limit but will
|
||||
|
@ -346,6 +350,7 @@ static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset,
|
|||
ptimer_run(m->timer, 1);
|
||||
}
|
||||
}
|
||||
ptimer_transaction_commit(m->timer);
|
||||
break;
|
||||
case A_TIMER1BGLOAD:
|
||||
/* Set the limit, but not the current count */
|
||||
|
@ -357,7 +362,9 @@ static void cmsdk_apb_dualtimer_write(void *opaque, hwaddr offset,
|
|||
if (!(m->control & R_CONTROL_SIZE_MASK)) {
|
||||
value &= 0xffff;
|
||||
}
|
||||
ptimer_transaction_begin(m->timer);
|
||||
ptimer_set_limit(m->timer, value, 0);
|
||||
ptimer_transaction_commit(m->timer);
|
||||
break;
|
||||
case A_TIMER1CONTROL:
|
||||
cmsdk_dualtimermod_write_control(m, value);
|
||||
|
@ -398,6 +405,7 @@ static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
|
|||
m->intstatus = 0;
|
||||
m->load = 0;
|
||||
m->value = 0xffffffff;
|
||||
ptimer_transaction_begin(m->timer);
|
||||
ptimer_stop(m->timer);
|
||||
/*
|
||||
* We start in free-running mode, with VALUE at 0xffffffff, and
|
||||
|
@ -406,6 +414,7 @@ static void cmsdk_dualtimermod_reset(CMSDKAPBDualTimerModule *m)
|
|||
*/
|
||||
ptimer_set_limit(m->timer, 0xffff, 1);
|
||||
ptimer_set_freq(m->timer, m->parent->pclk_frq);
|
||||
ptimer_transaction_commit(m->timer);
|
||||
}
|
||||
|
||||
static void cmsdk_apb_dualtimer_reset(DeviceState *dev)
|
||||
|
@ -450,10 +459,9 @@ static void cmsdk_apb_dualtimer_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
for (i = 0; i < ARRAY_SIZE(s->timermod); i++) {
|
||||
CMSDKAPBDualTimerModule *m = &s->timermod[i];
|
||||
QEMUBH *bh = qemu_bh_new(cmsdk_dualtimermod_tick, m);
|
||||
|
||||
m->parent = s;
|
||||
m->timer = ptimer_init(bh,
|
||||
m->timer = ptimer_init(cmsdk_dualtimermod_tick, m,
|
||||
PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
|
||||
PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
|
||||
PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qapi/error.h"
|
||||
#include "trace.h"
|
||||
|
@ -121,14 +120,17 @@ static void cmsdk_apb_timer_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
"CMSDK APB timer: EXTIN input not supported\n");
|
||||
}
|
||||
s->ctrl = value & 0xf;
|
||||
ptimer_transaction_begin(s->timer);
|
||||
if (s->ctrl & R_CTRL_EN_MASK) {
|
||||
ptimer_run(s->timer, ptimer_get_limit(s->timer) == 0);
|
||||
} else {
|
||||
ptimer_stop(s->timer);
|
||||
}
|
||||
ptimer_transaction_commit(s->timer);
|
||||
break;
|
||||
case A_RELOAD:
|
||||
/* Writing to reload also sets the current timer value */
|
||||
ptimer_transaction_begin(s->timer);
|
||||
if (!value) {
|
||||
ptimer_stop(s->timer);
|
||||
}
|
||||
|
@ -140,8 +142,10 @@ static void cmsdk_apb_timer_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
*/
|
||||
ptimer_run(s->timer, 0);
|
||||
}
|
||||
ptimer_transaction_commit(s->timer);
|
||||
break;
|
||||
case A_VALUE:
|
||||
ptimer_transaction_begin(s->timer);
|
||||
if (!value && !ptimer_get_limit(s->timer)) {
|
||||
ptimer_stop(s->timer);
|
||||
}
|
||||
|
@ -149,6 +153,7 @@ static void cmsdk_apb_timer_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
if (value && (s->ctrl & R_CTRL_EN_MASK)) {
|
||||
ptimer_run(s->timer, ptimer_get_limit(s->timer) == 0);
|
||||
}
|
||||
ptimer_transaction_commit(s->timer);
|
||||
break;
|
||||
case A_INTSTATUS:
|
||||
/* Just one bit, which is W1C. */
|
||||
|
@ -191,9 +196,11 @@ static void cmsdk_apb_timer_reset(DeviceState *dev)
|
|||
trace_cmsdk_apb_timer_reset();
|
||||
s->ctrl = 0;
|
||||
s->intstatus = 0;
|
||||
ptimer_transaction_begin(s->timer);
|
||||
ptimer_stop(s->timer);
|
||||
/* Set the limit and the count */
|
||||
ptimer_set_limit(s->timer, 0, 1);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
}
|
||||
|
||||
static void cmsdk_apb_timer_init(Object *obj)
|
||||
|
@ -210,21 +217,21 @@ static void cmsdk_apb_timer_init(Object *obj)
|
|||
static void cmsdk_apb_timer_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CMSDKAPBTIMER *s = CMSDK_APB_TIMER(dev);
|
||||
QEMUBH *bh;
|
||||
|
||||
if (s->pclk_frq == 0) {
|
||||
error_setg(errp, "CMSDK APB timer: pclk-frq property must be set");
|
||||
return;
|
||||
}
|
||||
|
||||
bh = qemu_bh_new(cmsdk_apb_timer_tick, s);
|
||||
s->timer = ptimer_init(bh,
|
||||
s->timer = ptimer_init(cmsdk_apb_timer_tick, s,
|
||||
PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
|
||||
PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
|
||||
PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
|
||||
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
|
||||
|
||||
ptimer_transaction_begin(s->timer);
|
||||
ptimer_set_freq(s->timer, s->pclk_frq);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
}
|
||||
|
||||
static const VMStateDescription cmsdk_apb_timer_vmstate = {
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/ptimer.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
|
@ -52,7 +51,9 @@ static void digic_timer_reset(DeviceState *dev)
|
|||
{
|
||||
DigicTimerState *s = DIGIC_TIMER(dev);
|
||||
|
||||
ptimer_transaction_begin(s->ptimer);
|
||||
ptimer_stop(s->ptimer);
|
||||
ptimer_transaction_commit(s->ptimer);
|
||||
s->control = 0;
|
||||
s->relvalue = 0;
|
||||
}
|
||||
|
@ -93,16 +94,20 @@ static void digic_timer_write(void *opaque, hwaddr offset,
|
|||
break;
|
||||
}
|
||||
|
||||
ptimer_transaction_begin(s->ptimer);
|
||||
if (value & DIGIC_TIMER_CONTROL_EN) {
|
||||
ptimer_run(s->ptimer, 0);
|
||||
}
|
||||
|
||||
s->control = (uint32_t)value;
|
||||
ptimer_transaction_commit(s->ptimer);
|
||||
break;
|
||||
|
||||
case DIGIC_TIMER_RELVALUE:
|
||||
s->relvalue = extract32(value, 0, 16);
|
||||
ptimer_transaction_begin(s->ptimer);
|
||||
ptimer_set_limit(s->ptimer, s->relvalue, 1);
|
||||
ptimer_transaction_commit(s->ptimer);
|
||||
break;
|
||||
|
||||
case DIGIC_TIMER_VALUE:
|
||||
|
@ -125,17 +130,24 @@ static const MemoryRegionOps digic_timer_ops = {
|
|||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static void digic_timer_tick(void *opaque)
|
||||
{
|
||||
/* Nothing to do on timer rollover */
|
||||
}
|
||||
|
||||
static void digic_timer_init(Object *obj)
|
||||
{
|
||||
DigicTimerState *s = DIGIC_TIMER(obj);
|
||||
|
||||
s->ptimer = ptimer_init(NULL, PTIMER_POLICY_DEFAULT);
|
||||
s->ptimer = ptimer_init(digic_timer_tick, NULL, PTIMER_POLICY_DEFAULT);
|
||||
|
||||
/*
|
||||
* FIXME: there is no documentation on Digic timer
|
||||
* frequency setup so let it always run at 1 MHz
|
||||
*/
|
||||
ptimer_transaction_begin(s->ptimer);
|
||||
ptimer_set_freq(s->ptimer, 1 * 1000 * 1000);
|
||||
ptimer_transaction_commit(s->ptimer);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &digic_timer_ops, s,
|
||||
TYPE_DIGIC_TIMER, 0x100);
|
||||
|
|
|
@ -328,9 +328,9 @@ static void etraxfs_timer_realize(DeviceState *dev, Error **errp)
|
|||
t->bh_t0 = qemu_bh_new(timer0_hit, t);
|
||||
t->bh_t1 = qemu_bh_new(timer1_hit, t);
|
||||
t->bh_wd = qemu_bh_new(watchdog_hit, t);
|
||||
t->ptimer_t0 = ptimer_init(t->bh_t0, PTIMER_POLICY_DEFAULT);
|
||||
t->ptimer_t1 = ptimer_init(t->bh_t1, PTIMER_POLICY_DEFAULT);
|
||||
t->ptimer_wd = ptimer_init(t->bh_wd, PTIMER_POLICY_DEFAULT);
|
||||
t->ptimer_t0 = ptimer_init_with_bh(t->bh_t0, PTIMER_POLICY_DEFAULT);
|
||||
t->ptimer_t1 = ptimer_init_with_bh(t->bh_t1, PTIMER_POLICY_DEFAULT);
|
||||
t->ptimer_wd = ptimer_init_with_bh(t->bh_wd, PTIMER_POLICY_DEFAULT);
|
||||
|
||||
sysbus_init_irq(sbd, &t->irq);
|
||||
sysbus_init_irq(sbd, &t->nmi);
|
||||
|
|
|
@ -58,7 +58,6 @@
|
|||
#include "hw/sysbus.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "hw/ptimer.h"
|
||||
|
||||
|
@ -364,6 +363,7 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s);
|
|||
|
||||
/*
|
||||
* Set counter of FRC global timer.
|
||||
* Must be called within exynos4210_gfrc_tx_begin/commit block.
|
||||
*/
|
||||
static void exynos4210_gfrc_set_count(Exynos4210MCTGT *s, uint64_t count)
|
||||
{
|
||||
|
@ -385,6 +385,7 @@ static uint64_t exynos4210_gfrc_get_count(Exynos4210MCTGT *s)
|
|||
|
||||
/*
|
||||
* Stop global FRC timer
|
||||
* Must be called within exynos4210_gfrc_tx_begin/commit block.
|
||||
*/
|
||||
static void exynos4210_gfrc_stop(Exynos4210MCTGT *s)
|
||||
{
|
||||
|
@ -395,6 +396,7 @@ static void exynos4210_gfrc_stop(Exynos4210MCTGT *s)
|
|||
|
||||
/*
|
||||
* Start global FRC timer
|
||||
* Must be called within exynos4210_gfrc_tx_begin/commit block.
|
||||
*/
|
||||
static void exynos4210_gfrc_start(Exynos4210MCTGT *s)
|
||||
{
|
||||
|
@ -403,6 +405,21 @@ static void exynos4210_gfrc_start(Exynos4210MCTGT *s)
|
|||
ptimer_run(s->ptimer_frc, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start ptimer transaction for global FRC timer; this is just for
|
||||
* consistency with the way we wrap operations like stop and run.
|
||||
*/
|
||||
static void exynos4210_gfrc_tx_begin(Exynos4210MCTGT *s)
|
||||
{
|
||||
ptimer_transaction_begin(s->ptimer_frc);
|
||||
}
|
||||
|
||||
/* Commit ptimer transaction for global FRC timer. */
|
||||
static void exynos4210_gfrc_tx_commit(Exynos4210MCTGT *s)
|
||||
{
|
||||
ptimer_transaction_commit(s->ptimer_frc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find next nearest Comparator. If current Comparator value equals to other
|
||||
* Comparator value, skip them both
|
||||
|
@ -492,6 +509,7 @@ static uint64_t exynos4210_gcomp_get_distance(Exynos4210MCTState *s, int32_t id)
|
|||
|
||||
/*
|
||||
* Restart global FRC timer
|
||||
* Must be called within exynos4210_gfrc_tx_begin/commit block.
|
||||
*/
|
||||
static void exynos4210_gfrc_restart(Exynos4210MCTState *s)
|
||||
{
|
||||
|
@ -589,6 +607,7 @@ static uint64_t exynos4210_lfrc_get_count(Exynos4210MCTLT *s)
|
|||
|
||||
/*
|
||||
* Set counter of FRC local timer.
|
||||
* Must be called from within exynos4210_lfrc_tx_begin/commit block.
|
||||
*/
|
||||
static void exynos4210_lfrc_update_count(Exynos4210MCTLT *s)
|
||||
{
|
||||
|
@ -601,6 +620,7 @@ static void exynos4210_lfrc_update_count(Exynos4210MCTLT *s)
|
|||
|
||||
/*
|
||||
* Start local FRC timer
|
||||
* Must be called from within exynos4210_lfrc_tx_begin/commit block.
|
||||
*/
|
||||
static void exynos4210_lfrc_start(Exynos4210MCTLT *s)
|
||||
{
|
||||
|
@ -609,12 +629,25 @@ static void exynos4210_lfrc_start(Exynos4210MCTLT *s)
|
|||
|
||||
/*
|
||||
* Stop local FRC timer
|
||||
* Must be called from within exynos4210_lfrc_tx_begin/commit block.
|
||||
*/
|
||||
static void exynos4210_lfrc_stop(Exynos4210MCTLT *s)
|
||||
{
|
||||
ptimer_stop(s->ptimer_frc);
|
||||
}
|
||||
|
||||
/* Start ptimer transaction for local FRC timer */
|
||||
static void exynos4210_lfrc_tx_begin(Exynos4210MCTLT *s)
|
||||
{
|
||||
ptimer_transaction_begin(s->ptimer_frc);
|
||||
}
|
||||
|
||||
/* Commit ptimer transaction for local FRC timer */
|
||||
static void exynos4210_lfrc_tx_commit(Exynos4210MCTLT *s)
|
||||
{
|
||||
ptimer_transaction_commit(s->ptimer_frc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local timer free running counter tick handler
|
||||
*/
|
||||
|
@ -701,6 +734,7 @@ static uint32_t exynos4210_ltick_int_get_cnto(struct tick_timer *s)
|
|||
|
||||
/*
|
||||
* Start local tick cnt timer.
|
||||
* Must be called within exynos4210_ltick_tx_begin/commit block.
|
||||
*/
|
||||
static void exynos4210_ltick_cnt_start(struct tick_timer *s)
|
||||
{
|
||||
|
@ -716,6 +750,7 @@ static void exynos4210_ltick_cnt_start(struct tick_timer *s)
|
|||
|
||||
/*
|
||||
* Stop local tick cnt timer.
|
||||
* Must be called within exynos4210_ltick_tx_begin/commit block.
|
||||
*/
|
||||
static void exynos4210_ltick_cnt_stop(struct tick_timer *s)
|
||||
{
|
||||
|
@ -733,6 +768,18 @@ static void exynos4210_ltick_cnt_stop(struct tick_timer *s)
|
|||
}
|
||||
}
|
||||
|
||||
/* Start ptimer transaction for local tick timer */
|
||||
static void exynos4210_ltick_tx_begin(struct tick_timer *s)
|
||||
{
|
||||
ptimer_transaction_begin(s->ptimer_tick);
|
||||
}
|
||||
|
||||
/* Commit ptimer transaction for local tick timer */
|
||||
static void exynos4210_ltick_tx_commit(struct tick_timer *s)
|
||||
{
|
||||
ptimer_transaction_commit(s->ptimer_tick);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get counter for CNT timer
|
||||
*/
|
||||
|
@ -778,6 +825,7 @@ static uint32_t exynos4210_ltick_cnt_get_cnto(struct tick_timer *s)
|
|||
|
||||
/*
|
||||
* Set new values of counters for CNT and INT timers
|
||||
* Must be called within exynos4210_ltick_tx_begin/commit block.
|
||||
*/
|
||||
static void exynos4210_ltick_set_cntb(struct tick_timer *s, uint32_t new_cnt,
|
||||
uint32_t new_int)
|
||||
|
@ -851,7 +899,9 @@ static void exynos4210_ltick_recalc_count(struct tick_timer *s)
|
|||
static void exynos4210_ltick_timer_init(struct tick_timer *s)
|
||||
{
|
||||
exynos4210_ltick_int_stop(s);
|
||||
exynos4210_ltick_tx_begin(s);
|
||||
exynos4210_ltick_cnt_stop(s);
|
||||
exynos4210_ltick_tx_commit(s);
|
||||
|
||||
s->count = 0;
|
||||
s->distance = 0;
|
||||
|
@ -933,6 +983,19 @@ static void exynos4210_ltick_event(void *opaque)
|
|||
exynos4210_ltick_int_start(&s->tick_timer);
|
||||
}
|
||||
|
||||
static void tx_ptimer_set_freq(ptimer_state *s, uint32_t freq)
|
||||
{
|
||||
/*
|
||||
* callers of exynos4210_mct_update_freq() never do anything
|
||||
* else that needs to be in the same ptimer transaction, so
|
||||
* to avoid a lot of repetition we have a convenience function
|
||||
* for begin/set_freq/commit.
|
||||
*/
|
||||
ptimer_transaction_begin(s);
|
||||
ptimer_set_freq(s, freq);
|
||||
ptimer_transaction_commit(s);
|
||||
}
|
||||
|
||||
/* update timer frequency */
|
||||
static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
|
||||
{
|
||||
|
@ -945,13 +1008,13 @@ static void exynos4210_mct_update_freq(Exynos4210MCTState *s)
|
|||
DPRINTF("freq=%dHz\n", s->freq);
|
||||
|
||||
/* global timer */
|
||||
ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
|
||||
tx_ptimer_set_freq(s->g_timer.ptimer_frc, s->freq);
|
||||
|
||||
/* local timer */
|
||||
ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);
|
||||
ptimer_set_freq(s->l_timer[0].ptimer_frc, s->freq);
|
||||
ptimer_set_freq(s->l_timer[1].tick_timer.ptimer_tick, s->freq);
|
||||
ptimer_set_freq(s->l_timer[1].ptimer_frc, s->freq);
|
||||
tx_ptimer_set_freq(s->l_timer[0].tick_timer.ptimer_tick, s->freq);
|
||||
tx_ptimer_set_freq(s->l_timer[0].ptimer_frc, s->freq);
|
||||
tx_ptimer_set_freq(s->l_timer[1].tick_timer.ptimer_tick, s->freq);
|
||||
tx_ptimer_set_freq(s->l_timer[1].ptimer_frc, s->freq);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -965,7 +1028,9 @@ static void exynos4210_mct_reset(DeviceState *d)
|
|||
|
||||
/* global timer */
|
||||
memset(&s->g_timer.reg, 0, sizeof(s->g_timer.reg));
|
||||
exynos4210_gfrc_tx_begin(&s->g_timer);
|
||||
exynos4210_gfrc_stop(&s->g_timer);
|
||||
exynos4210_gfrc_tx_commit(&s->g_timer);
|
||||
|
||||
/* local timer */
|
||||
memset(s->l_timer[0].reg.cnt, 0, sizeof(s->l_timer[0].reg.cnt));
|
||||
|
@ -978,7 +1043,9 @@ static void exynos4210_mct_reset(DeviceState *d)
|
|||
s->l_timer[i].tick_timer.count = 0;
|
||||
s->l_timer[i].tick_timer.distance = 0;
|
||||
s->l_timer[i].tick_timer.progress = 0;
|
||||
exynos4210_lfrc_tx_begin(&s->l_timer[i]);
|
||||
ptimer_stop(s->l_timer[i].ptimer_frc);
|
||||
exynos4210_lfrc_tx_commit(&s->l_timer[i]);
|
||||
|
||||
exynos4210_ltick_timer_init(&s->l_timer[i].tick_timer);
|
||||
}
|
||||
|
@ -1144,7 +1211,9 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
|
|||
}
|
||||
|
||||
s->g_timer.reg.cnt = new_frc;
|
||||
exynos4210_gfrc_tx_begin(&s->g_timer);
|
||||
exynos4210_gfrc_restart(s);
|
||||
exynos4210_gfrc_tx_commit(&s->g_timer);
|
||||
break;
|
||||
|
||||
case G_CNT_WSTAT:
|
||||
|
@ -1168,7 +1237,9 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
|
|||
s->g_timer.reg.wstat |= G_WSTAT_COMP_L(index);
|
||||
}
|
||||
|
||||
exynos4210_gfrc_tx_begin(&s->g_timer);
|
||||
exynos4210_gfrc_restart(s);
|
||||
exynos4210_gfrc_tx_commit(&s->g_timer);
|
||||
break;
|
||||
|
||||
case G_TCON:
|
||||
|
@ -1178,6 +1249,8 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
|
|||
|
||||
DPRINTF("global timer write to reg.g_tcon %llx\n", value);
|
||||
|
||||
exynos4210_gfrc_tx_begin(&s->g_timer);
|
||||
|
||||
/* Start FRC if transition from disabled to enabled */
|
||||
if ((value & G_TCON_TIMER_ENABLE) > (old_val &
|
||||
G_TCON_TIMER_ENABLE)) {
|
||||
|
@ -1195,6 +1268,8 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
|
|||
exynos4210_gfrc_restart(s);
|
||||
}
|
||||
}
|
||||
|
||||
exynos4210_gfrc_tx_commit(&s->g_timer);
|
||||
break;
|
||||
|
||||
case G_INT_CSTAT:
|
||||
|
@ -1245,6 +1320,7 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
|
|||
s->l_timer[lt_i].reg.wstat |= L_WSTAT_TCON_WRITE;
|
||||
s->l_timer[lt_i].reg.tcon = value;
|
||||
|
||||
exynos4210_ltick_tx_begin(&s->l_timer[lt_i].tick_timer);
|
||||
/* Stop local CNT */
|
||||
if ((value & L_TCON_TICK_START) <
|
||||
(old_val & L_TCON_TICK_START)) {
|
||||
|
@ -1272,8 +1348,10 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
|
|||
DPRINTF("local timer[%d] start int\n", lt_i);
|
||||
exynos4210_ltick_int_start(&s->l_timer[lt_i].tick_timer);
|
||||
}
|
||||
exynos4210_ltick_tx_commit(&s->l_timer[lt_i].tick_timer);
|
||||
|
||||
/* Start or Stop local FRC if TCON changed */
|
||||
exynos4210_lfrc_tx_begin(&s->l_timer[lt_i]);
|
||||
if ((value & L_TCON_FRC_START) >
|
||||
(s->l_timer[lt_i].reg.tcon & L_TCON_FRC_START)) {
|
||||
DPRINTF("local timer[%d] start frc\n", lt_i);
|
||||
|
@ -1284,6 +1362,7 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
|
|||
DPRINTF("local timer[%d] stop frc\n", lt_i);
|
||||
exynos4210_lfrc_stop(&s->l_timer[lt_i]);
|
||||
}
|
||||
exynos4210_lfrc_tx_commit(&s->l_timer[lt_i]);
|
||||
break;
|
||||
|
||||
case L0_TCNTB: case L1_TCNTB:
|
||||
|
@ -1295,8 +1374,10 @@ static void exynos4210_mct_write(void *opaque, hwaddr offset,
|
|||
* Due to this we should reload timer to nearest moment when CNT is
|
||||
* expired and then in event handler update tcntb to new TCNTB value.
|
||||
*/
|
||||
exynos4210_ltick_tx_begin(&s->l_timer[lt_i].tick_timer);
|
||||
exynos4210_ltick_set_cntb(&s->l_timer[lt_i].tick_timer, value,
|
||||
s->l_timer[lt_i].tick_timer.icntb);
|
||||
exynos4210_ltick_tx_commit(&s->l_timer[lt_i].tick_timer);
|
||||
|
||||
s->l_timer[lt_i].reg.wstat |= L_WSTAT_TCNTB_WRITE;
|
||||
s->l_timer[lt_i].reg.cnt[L_REG_CNT_TCNTB] = value;
|
||||
|
@ -1425,20 +1506,20 @@ static void exynos4210_mct_init(Object *obj)
|
|||
int i;
|
||||
Exynos4210MCTState *s = EXYNOS4210_MCT(obj);
|
||||
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
|
||||
QEMUBH *bh[2];
|
||||
|
||||
/* Global timer */
|
||||
bh[0] = qemu_bh_new(exynos4210_gfrc_event, s);
|
||||
s->g_timer.ptimer_frc = ptimer_init(bh[0], PTIMER_POLICY_DEFAULT);
|
||||
s->g_timer.ptimer_frc = ptimer_init(exynos4210_gfrc_event, s,
|
||||
PTIMER_POLICY_DEFAULT);
|
||||
memset(&s->g_timer.reg, 0, sizeof(struct gregs));
|
||||
|
||||
/* Local timers */
|
||||
for (i = 0; i < 2; i++) {
|
||||
bh[0] = qemu_bh_new(exynos4210_ltick_event, &s->l_timer[i]);
|
||||
bh[1] = qemu_bh_new(exynos4210_lfrc_event, &s->l_timer[i]);
|
||||
s->l_timer[i].tick_timer.ptimer_tick =
|
||||
ptimer_init(bh[0], PTIMER_POLICY_DEFAULT);
|
||||
s->l_timer[i].ptimer_frc = ptimer_init(bh[1], PTIMER_POLICY_DEFAULT);
|
||||
ptimer_init(exynos4210_ltick_event, &s->l_timer[i],
|
||||
PTIMER_POLICY_DEFAULT);
|
||||
s->l_timer[i].ptimer_frc =
|
||||
ptimer_init(exynos4210_lfrc_event, &s->l_timer[i],
|
||||
PTIMER_POLICY_DEFAULT);
|
||||
s->l_timer[i].id = i;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "hw/sysbus.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "hw/ptimer.h"
|
||||
|
||||
|
@ -150,7 +149,9 @@ static const VMStateDescription vmstate_exynos4210_pwm_state = {
|
|||
};
|
||||
|
||||
/*
|
||||
* PWM update frequency
|
||||
* PWM update frequency.
|
||||
* Must be called within a ptimer_transaction_begin/commit block
|
||||
* for s->timer[id].ptimer.
|
||||
*/
|
||||
static void exynos4210_pwm_update_freq(Exynos4210PWMState *s, uint32_t id)
|
||||
{
|
||||
|
@ -281,12 +282,15 @@ static void exynos4210_pwm_write(void *opaque, hwaddr offset,
|
|||
|
||||
/* update timers frequencies */
|
||||
for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
|
||||
ptimer_transaction_begin(s->timer[i].ptimer);
|
||||
exynos4210_pwm_update_freq(s, s->timer[i].id);
|
||||
ptimer_transaction_commit(s->timer[i].ptimer);
|
||||
}
|
||||
break;
|
||||
|
||||
case TCON:
|
||||
for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
|
||||
ptimer_transaction_begin(s->timer[i].ptimer);
|
||||
if ((value & TCON_TIMER_MANUAL_UPD(i)) >
|
||||
(s->reg_tcon & TCON_TIMER_MANUAL_UPD(i))) {
|
||||
/*
|
||||
|
@ -315,6 +319,7 @@ static void exynos4210_pwm_write(void *opaque, hwaddr offset,
|
|||
ptimer_stop(s->timer[i].ptimer);
|
||||
DPRINTF("stop timer %d\n", i);
|
||||
}
|
||||
ptimer_transaction_commit(s->timer[i].ptimer);
|
||||
}
|
||||
s->reg_tcon = value;
|
||||
break;
|
||||
|
@ -369,8 +374,10 @@ static void exynos4210_pwm_reset(DeviceState *d)
|
|||
s->timer[i].reg_tcmpb = 0;
|
||||
s->timer[i].reg_tcntb = 0;
|
||||
|
||||
ptimer_transaction_begin(s->timer[i].ptimer);
|
||||
exynos4210_pwm_update_freq(s, s->timer[i].id);
|
||||
ptimer_stop(s->timer[i].ptimer);
|
||||
ptimer_transaction_commit(s->timer[i].ptimer);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,12 +395,12 @@ static void exynos4210_pwm_init(Object *obj)
|
|||
Exynos4210PWMState *s = EXYNOS4210_PWM(obj);
|
||||
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
|
||||
int i;
|
||||
QEMUBH *bh;
|
||||
|
||||
for (i = 0; i < EXYNOS4210_PWM_TIMERS_NUM; i++) {
|
||||
bh = qemu_bh_new(exynos4210_pwm_tick, &s->timer[i]);
|
||||
sysbus_init_irq(dev, &s->timer[i].irq);
|
||||
s->timer[i].ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
|
||||
s->timer[i].ptimer = ptimer_init(exynos4210_pwm_tick,
|
||||
&s->timer[i],
|
||||
PTIMER_POLICY_DEFAULT);
|
||||
s->timer[i].id = i;
|
||||
s->timer[i].parent = s;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "migration/vmstate.h"
|
||||
|
@ -195,6 +194,7 @@ static void check_alarm_raise(Exynos4210RTCState *s)
|
|||
* RTC update frequency
|
||||
* Parameters:
|
||||
* reg_value - current RTCCON register or his new value
|
||||
* Must be called within a ptimer_transaction_begin/commit block for s->ptimer.
|
||||
*/
|
||||
static void exynos4210_rtc_update_freq(Exynos4210RTCState *s,
|
||||
uint32_t reg_value)
|
||||
|
@ -401,6 +401,8 @@ static void exynos4210_rtc_write(void *opaque, hwaddr offset,
|
|||
}
|
||||
break;
|
||||
case RTCCON:
|
||||
ptimer_transaction_begin(s->ptimer_1Hz);
|
||||
ptimer_transaction_begin(s->ptimer);
|
||||
if (value & RTC_ENABLE) {
|
||||
exynos4210_rtc_update_freq(s, value);
|
||||
}
|
||||
|
@ -430,6 +432,8 @@ static void exynos4210_rtc_write(void *opaque, hwaddr offset,
|
|||
ptimer_stop(s->ptimer);
|
||||
}
|
||||
}
|
||||
ptimer_transaction_commit(s->ptimer_1Hz);
|
||||
ptimer_transaction_commit(s->ptimer);
|
||||
s->reg_rtccon = value;
|
||||
break;
|
||||
case TICCNT:
|
||||
|
@ -537,9 +541,13 @@ static void exynos4210_rtc_reset(DeviceState *d)
|
|||
|
||||
s->reg_curticcnt = 0;
|
||||
|
||||
ptimer_transaction_begin(s->ptimer);
|
||||
exynos4210_rtc_update_freq(s, s->reg_rtccon);
|
||||
ptimer_stop(s->ptimer);
|
||||
ptimer_transaction_commit(s->ptimer);
|
||||
ptimer_transaction_begin(s->ptimer_1Hz);
|
||||
ptimer_stop(s->ptimer_1Hz);
|
||||
ptimer_transaction_commit(s->ptimer_1Hz);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps exynos4210_rtc_ops = {
|
||||
|
@ -555,16 +563,18 @@ static void exynos4210_rtc_init(Object *obj)
|
|||
{
|
||||
Exynos4210RTCState *s = EXYNOS4210_RTC(obj);
|
||||
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
|
||||
QEMUBH *bh;
|
||||
|
||||
bh = qemu_bh_new(exynos4210_rtc_tick, s);
|
||||
s->ptimer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
|
||||
s->ptimer = ptimer_init(exynos4210_rtc_tick, s, PTIMER_POLICY_DEFAULT);
|
||||
ptimer_transaction_begin(s->ptimer);
|
||||
ptimer_set_freq(s->ptimer, RTC_BASE_FREQ);
|
||||
exynos4210_rtc_update_freq(s, 0);
|
||||
ptimer_transaction_commit(s->ptimer);
|
||||
|
||||
bh = qemu_bh_new(exynos4210_rtc_1Hz_tick, s);
|
||||
s->ptimer_1Hz = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
|
||||
s->ptimer_1Hz = ptimer_init(exynos4210_rtc_1Hz_tick,
|
||||
s, PTIMER_POLICY_DEFAULT);
|
||||
ptimer_transaction_begin(s->ptimer_1Hz);
|
||||
ptimer_set_freq(s->ptimer_1Hz, RTC_BASE_FREQ);
|
||||
ptimer_transaction_commit(s->ptimer_1Hz);
|
||||
|
||||
sysbus_init_irq(dev, &s->alm_irq);
|
||||
sysbus_init_irq(dev, &s->tick_irq);
|
||||
|
|
|
@ -366,7 +366,7 @@ static void grlib_gptimer_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
timer->unit = unit;
|
||||
timer->bh = qemu_bh_new(grlib_gptimer_hit, timer);
|
||||
timer->ptimer = ptimer_init(timer->bh, PTIMER_POLICY_DEFAULT);
|
||||
timer->ptimer = ptimer_init_with_bh(timer->bh, PTIMER_POLICY_DEFAULT);
|
||||
timer->id = i;
|
||||
|
||||
/* One IRQ line for each timer */
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
#include "migration/vmstate.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/misc/imx_ccm.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
|
@ -74,6 +73,10 @@ static void imx_epit_update_int(IMXEPITState *s)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Must be called from within a ptimer_transaction_begin/commit block
|
||||
* for both s->timer_cmp and s->timer_reload.
|
||||
*/
|
||||
static void imx_epit_set_freq(IMXEPITState *s)
|
||||
{
|
||||
uint32_t clksrc;
|
||||
|
@ -105,6 +108,8 @@ static void imx_epit_reset(DeviceState *dev)
|
|||
s->lr = EPIT_TIMER_MAX;
|
||||
s->cmp = 0;
|
||||
s->cnt = 0;
|
||||
ptimer_transaction_begin(s->timer_cmp);
|
||||
ptimer_transaction_begin(s->timer_reload);
|
||||
/* stop both timers */
|
||||
ptimer_stop(s->timer_cmp);
|
||||
ptimer_stop(s->timer_reload);
|
||||
|
@ -117,6 +122,8 @@ static void imx_epit_reset(DeviceState *dev)
|
|||
/* if the timer is still enabled, restart it */
|
||||
ptimer_run(s->timer_reload, 0);
|
||||
}
|
||||
ptimer_transaction_commit(s->timer_cmp);
|
||||
ptimer_transaction_commit(s->timer_reload);
|
||||
}
|
||||
|
||||
static uint32_t imx_epit_update_count(IMXEPITState *s)
|
||||
|
@ -164,6 +171,7 @@ static uint64_t imx_epit_read(void *opaque, hwaddr offset, unsigned size)
|
|||
return reg_value;
|
||||
}
|
||||
|
||||
/* Must be called from ptimer_transaction_begin/commit block for s->timer_cmp */
|
||||
static void imx_epit_reload_compare_timer(IMXEPITState *s)
|
||||
{
|
||||
if ((s->cr & (CR_EN | CR_OCIEN)) == (CR_EN | CR_OCIEN)) {
|
||||
|
@ -191,6 +199,8 @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
|
||||
switch (offset >> 2) {
|
||||
case 0: /* CR */
|
||||
ptimer_transaction_begin(s->timer_cmp);
|
||||
ptimer_transaction_begin(s->timer_reload);
|
||||
|
||||
oldcr = s->cr;
|
||||
s->cr = value & 0x03ffffff;
|
||||
|
@ -231,6 +241,9 @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
} else {
|
||||
ptimer_stop(s->timer_cmp);
|
||||
}
|
||||
|
||||
ptimer_transaction_commit(s->timer_cmp);
|
||||
ptimer_transaction_commit(s->timer_reload);
|
||||
break;
|
||||
|
||||
case 1: /* SR - ACK*/
|
||||
|
@ -244,6 +257,8 @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
case 2: /* LR - set ticks */
|
||||
s->lr = value;
|
||||
|
||||
ptimer_transaction_begin(s->timer_cmp);
|
||||
ptimer_transaction_begin(s->timer_reload);
|
||||
if (s->cr & CR_RLD) {
|
||||
/* Also set the limit if the LRD bit is set */
|
||||
/* If IOVW bit is set then set the timer value */
|
||||
|
@ -255,12 +270,16 @@ static void imx_epit_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
}
|
||||
|
||||
imx_epit_reload_compare_timer(s);
|
||||
ptimer_transaction_commit(s->timer_cmp);
|
||||
ptimer_transaction_commit(s->timer_reload);
|
||||
break;
|
||||
|
||||
case 3: /* CMP */
|
||||
s->cmp = value;
|
||||
|
||||
ptimer_transaction_begin(s->timer_cmp);
|
||||
imx_epit_reload_compare_timer(s);
|
||||
ptimer_transaction_commit(s->timer_cmp);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -281,6 +300,11 @@ static void imx_epit_cmp(void *opaque)
|
|||
imx_epit_update_int(s);
|
||||
}
|
||||
|
||||
static void imx_epit_reload(void *opaque)
|
||||
{
|
||||
/* No action required on rollover of timer_reload */
|
||||
}
|
||||
|
||||
static const MemoryRegionOps imx_epit_ops = {
|
||||
.read = imx_epit_read,
|
||||
.write = imx_epit_write,
|
||||
|
@ -308,7 +332,6 @@ static void imx_epit_realize(DeviceState *dev, Error **errp)
|
|||
{
|
||||
IMXEPITState *s = IMX_EPIT(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
QEMUBH *bh;
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
|
@ -317,10 +340,9 @@ static void imx_epit_realize(DeviceState *dev, Error **errp)
|
|||
0x00001000);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
|
||||
s->timer_reload = ptimer_init(NULL, PTIMER_POLICY_DEFAULT);
|
||||
s->timer_reload = ptimer_init(imx_epit_reload, s, PTIMER_POLICY_DEFAULT);
|
||||
|
||||
bh = qemu_bh_new(imx_epit_cmp, s);
|
||||
s->timer_cmp = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
|
||||
s->timer_cmp = ptimer_init(imx_epit_cmp, s, PTIMER_POLICY_DEFAULT);
|
||||
}
|
||||
|
||||
static void imx_epit_class_init(ObjectClass *klass, void *data)
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "hw/irq.h"
|
||||
#include "hw/timer/imx_gpt.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
|
@ -127,6 +126,7 @@ static const IMXClk imx7_gpt_clocks[] = {
|
|||
CLK_NONE, /* 111 not defined */
|
||||
};
|
||||
|
||||
/* Must be called from within ptimer_transaction_begin/commit block */
|
||||
static void imx_gpt_set_freq(IMXGPTState *s)
|
||||
{
|
||||
uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3);
|
||||
|
@ -167,6 +167,7 @@ static inline uint32_t imx_gpt_find_limit(uint32_t count, uint32_t reg,
|
|||
return timeout;
|
||||
}
|
||||
|
||||
/* Must be called from within ptimer_transaction_begin/commit block */
|
||||
static void imx_gpt_compute_next_timeout(IMXGPTState *s, bool event)
|
||||
{
|
||||
uint32_t timeout = GPT_TIMER_MAX;
|
||||
|
@ -313,6 +314,7 @@ static uint64_t imx_gpt_read(void *opaque, hwaddr offset, unsigned size)
|
|||
|
||||
static void imx_gpt_reset_common(IMXGPTState *s, bool is_soft_reset)
|
||||
{
|
||||
ptimer_transaction_begin(s->timer);
|
||||
/* stop timer */
|
||||
ptimer_stop(s->timer);
|
||||
|
||||
|
@ -350,6 +352,7 @@ static void imx_gpt_reset_common(IMXGPTState *s, bool is_soft_reset)
|
|||
if (s->freq && (s->cr & GPT_CR_EN)) {
|
||||
ptimer_run(s->timer, 1);
|
||||
}
|
||||
ptimer_transaction_commit(s->timer);
|
||||
}
|
||||
|
||||
static void imx_gpt_soft_reset(DeviceState *dev)
|
||||
|
@ -382,6 +385,7 @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
imx_gpt_soft_reset(DEVICE(s));
|
||||
} else {
|
||||
/* set our freq, as the source might have changed */
|
||||
ptimer_transaction_begin(s->timer);
|
||||
imx_gpt_set_freq(s);
|
||||
|
||||
if ((oldreg ^ s->cr) & GPT_CR_EN) {
|
||||
|
@ -397,12 +401,15 @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
ptimer_stop(s->timer);
|
||||
}
|
||||
}
|
||||
ptimer_transaction_commit(s->timer);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: /* Prescaler */
|
||||
s->pr = value & 0xfff;
|
||||
ptimer_transaction_begin(s->timer);
|
||||
imx_gpt_set_freq(s);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
break;
|
||||
|
||||
case 2: /* SR */
|
||||
|
@ -414,13 +421,16 @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
s->ir = value & 0x3f;
|
||||
imx_gpt_update_int(s);
|
||||
|
||||
ptimer_transaction_begin(s->timer);
|
||||
imx_gpt_compute_next_timeout(s, false);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
|
||||
break;
|
||||
|
||||
case 4: /* OCR1 -- output compare register */
|
||||
s->ocr1 = value;
|
||||
|
||||
ptimer_transaction_begin(s->timer);
|
||||
/* In non-freerun mode, reset count when this register is written */
|
||||
if (!(s->cr & GPT_CR_FRR)) {
|
||||
s->next_timeout = GPT_TIMER_MAX;
|
||||
|
@ -429,6 +439,7 @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
|
||||
/* compute the new timeout */
|
||||
imx_gpt_compute_next_timeout(s, false);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -436,7 +447,9 @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
s->ocr2 = value;
|
||||
|
||||
/* compute the new timeout */
|
||||
ptimer_transaction_begin(s->timer);
|
||||
imx_gpt_compute_next_timeout(s, false);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -444,7 +457,9 @@ static void imx_gpt_write(void *opaque, hwaddr offset, uint64_t value,
|
|||
s->ocr3 = value;
|
||||
|
||||
/* compute the new timeout */
|
||||
ptimer_transaction_begin(s->timer);
|
||||
imx_gpt_compute_next_timeout(s, false);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -484,15 +499,13 @@ static void imx_gpt_realize(DeviceState *dev, Error **errp)
|
|||
{
|
||||
IMXGPTState *s = IMX_GPT(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
QEMUBH *bh;
|
||||
|
||||
sysbus_init_irq(sbd, &s->irq);
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &imx_gpt_ops, s, TYPE_IMX_GPT,
|
||||
0x00001000);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
|
||||
bh = qemu_bh_new(imx_gpt_timeout, s);
|
||||
s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
|
||||
s->timer = ptimer_init(imx_gpt_timeout, s, PTIMER_POLICY_DEFAULT);
|
||||
}
|
||||
|
||||
static void imx_gpt_class_init(ObjectClass *klass, void *data)
|
||||
|
|
|
@ -196,7 +196,7 @@ static void lm32_timer_realize(DeviceState *dev, Error **errp)
|
|||
LM32TimerState *s = LM32_TIMER(dev);
|
||||
|
||||
s->bh = qemu_bh_new(timer_hit, s);
|
||||
s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT);
|
||||
s->ptimer = ptimer_init_with_bh(s->bh, PTIMER_POLICY_DEFAULT);
|
||||
|
||||
ptimer_set_freq(s->ptimer, s->freq_hz);
|
||||
}
|
||||
|
|
|
@ -294,8 +294,8 @@ static void milkymist_sysctl_realize(DeviceState *dev, Error **errp)
|
|||
|
||||
s->bh0 = qemu_bh_new(timer0_hit, s);
|
||||
s->bh1 = qemu_bh_new(timer1_hit, s);
|
||||
s->ptimer0 = ptimer_init(s->bh0, PTIMER_POLICY_DEFAULT);
|
||||
s->ptimer1 = ptimer_init(s->bh1, PTIMER_POLICY_DEFAULT);
|
||||
s->ptimer0 = ptimer_init_with_bh(s->bh0, PTIMER_POLICY_DEFAULT);
|
||||
s->ptimer1 = ptimer_init_with_bh(s->bh1, PTIMER_POLICY_DEFAULT);
|
||||
|
||||
ptimer_set_freq(s->ptimer0, s->freq_hz);
|
||||
ptimer_set_freq(s->ptimer1, s->freq_hz);
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/log.h"
|
||||
#include "hw/irq.h"
|
||||
|
@ -67,6 +66,7 @@ static void timer_update_irq(struct Msf2Timer *st)
|
|||
qemu_set_irq(st->irq, (ier && isr));
|
||||
}
|
||||
|
||||
/* Must be called from within a ptimer_transaction_begin/commit block */
|
||||
static void timer_update(struct Msf2Timer *st)
|
||||
{
|
||||
uint64_t count;
|
||||
|
@ -159,7 +159,9 @@ timer_write(void *opaque, hwaddr offset,
|
|||
switch (addr) {
|
||||
case R_TIM_CTRL:
|
||||
st->regs[R_TIM_CTRL] = value;
|
||||
ptimer_transaction_begin(st->ptimer);
|
||||
timer_update(st);
|
||||
ptimer_transaction_commit(st->ptimer);
|
||||
break;
|
||||
|
||||
case R_TIM_RIS:
|
||||
|
@ -171,7 +173,9 @@ timer_write(void *opaque, hwaddr offset,
|
|||
case R_TIM_LOADVAL:
|
||||
st->regs[R_TIM_LOADVAL] = value;
|
||||
if (st->regs[R_TIM_CTRL] & TIMER_CTRL_ENBL) {
|
||||
ptimer_transaction_begin(st->ptimer);
|
||||
timer_update(st);
|
||||
ptimer_transaction_commit(st->ptimer);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -228,9 +232,10 @@ static void mss_timer_init(Object *obj)
|
|||
for (i = 0; i < NUM_TIMERS; i++) {
|
||||
struct Msf2Timer *st = &t->timers[i];
|
||||
|
||||
st->bh = qemu_bh_new(timer_hit, st);
|
||||
st->ptimer = ptimer_init(st->bh, PTIMER_POLICY_DEFAULT);
|
||||
st->ptimer = ptimer_init(timer_hit, st, PTIMER_POLICY_DEFAULT);
|
||||
ptimer_transaction_begin(st->ptimer);
|
||||
ptimer_set_freq(st->ptimer, t->freq_hz);
|
||||
ptimer_transaction_commit(st->ptimer);
|
||||
sysbus_init_irq(SYS_BUS_DEVICE(obj), &st->irq);
|
||||
}
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ static void puv3_ost_realize(DeviceState *dev, Error **errp)
|
|||
sysbus_init_irq(sbd, &s->irq);
|
||||
|
||||
s->bh = qemu_bh_new(puv3_ost_tick, s);
|
||||
s->ptimer = ptimer_init(s->bh, PTIMER_POLICY_DEFAULT);
|
||||
s->ptimer = ptimer_init_with_bh(s->bh, PTIMER_POLICY_DEFAULT);
|
||||
ptimer_set_freq(s->ptimer, 50 * 1000 * 1000);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &puv3_ost_ops, s, "puv3_ost",
|
||||
|
|
|
@ -204,7 +204,7 @@ static void *sh_timer_init(uint32_t freq, int feat, qemu_irq irq)
|
|||
s->irq = irq;
|
||||
|
||||
bh = qemu_bh_new(sh_timer_tick, s);
|
||||
s->timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
|
||||
s->timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
|
||||
|
||||
sh_timer_write(s, OFFSET_TCOR >> 2, s->tcor);
|
||||
sh_timer_write(s, OFFSET_TCNT >> 2, s->tcnt);
|
||||
|
|
|
@ -393,7 +393,7 @@ static void slavio_timer_init(Object *obj)
|
|||
tc->timer_index = i;
|
||||
|
||||
bh = qemu_bh_new(slavio_timer_irq, tc);
|
||||
s->cputimer[i].timer = ptimer_init(bh, PTIMER_POLICY_DEFAULT);
|
||||
s->cputimer[i].timer = ptimer_init_with_bh(bh, PTIMER_POLICY_DEFAULT);
|
||||
ptimer_set_period(s->cputimer[i].timer, TIMER_PERIOD);
|
||||
|
||||
size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE;
|
||||
|
|
|
@ -221,7 +221,7 @@ static void xilinx_timer_realize(DeviceState *dev, Error **errp)
|
|||
xt->parent = t;
|
||||
xt->nr = i;
|
||||
xt->bh = qemu_bh_new(timer_hit, xt);
|
||||
xt->ptimer = ptimer_init(xt->bh, PTIMER_POLICY_DEFAULT);
|
||||
xt->ptimer = ptimer_init_with_bh(xt->bh, PTIMER_POLICY_DEFAULT);
|
||||
ptimer_set_freq(xt->ptimer, t->freq_hz);
|
||||
}
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "qemu/log.h"
|
||||
#include "trace.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/module.h"
|
||||
#include "sysemu/watchdog.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
@ -200,8 +199,10 @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset,
|
|||
* Reset the load value and the current count, and make sure
|
||||
* we're counting.
|
||||
*/
|
||||
ptimer_transaction_begin(s->timer);
|
||||
ptimer_set_limit(s->timer, value, 1);
|
||||
ptimer_run(s->timer, 0);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
break;
|
||||
case A_WDOGCONTROL:
|
||||
if (s->is_luminary && 0 != (R_WDOGCONTROL_INTEN_MASK & s->control)) {
|
||||
|
@ -217,7 +218,9 @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset,
|
|||
break;
|
||||
case A_WDOGINTCLR:
|
||||
s->intstatus = 0;
|
||||
ptimer_transaction_begin(s->timer);
|
||||
ptimer_set_count(s->timer, ptimer_get_limit(s->timer));
|
||||
ptimer_transaction_commit(s->timer);
|
||||
cmsdk_apb_watchdog_update(s);
|
||||
break;
|
||||
case A_WDOGLOCK:
|
||||
|
@ -299,8 +302,10 @@ static void cmsdk_apb_watchdog_reset(DeviceState *dev)
|
|||
s->itop = 0;
|
||||
s->resetstatus = 0;
|
||||
/* Set the limit and the count */
|
||||
ptimer_transaction_begin(s->timer);
|
||||
ptimer_set_limit(s->timer, 0xffffffff, 1);
|
||||
ptimer_run(s->timer, 0);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
}
|
||||
|
||||
static void cmsdk_apb_watchdog_init(Object *obj)
|
||||
|
@ -320,7 +325,6 @@ static void cmsdk_apb_watchdog_init(Object *obj)
|
|||
static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
CMSDKAPBWatchdog *s = CMSDK_APB_WATCHDOG(dev);
|
||||
QEMUBH *bh;
|
||||
|
||||
if (s->wdogclk_frq == 0) {
|
||||
error_setg(errp,
|
||||
|
@ -328,14 +332,15 @@ static void cmsdk_apb_watchdog_realize(DeviceState *dev, Error **errp)
|
|||
return;
|
||||
}
|
||||
|
||||
bh = qemu_bh_new(cmsdk_apb_watchdog_tick, s);
|
||||
s->timer = ptimer_init(bh,
|
||||
s->timer = ptimer_init(cmsdk_apb_watchdog_tick, s,
|
||||
PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD |
|
||||
PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT |
|
||||
PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
|
||||
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
|
||||
|
||||
ptimer_transaction_begin(s->timer);
|
||||
ptimer_set_freq(s->timer, s->wdogclk_frq);
|
||||
ptimer_transaction_commit(s->timer);
|
||||
}
|
||||
|
||||
static const VMStateDescription cmsdk_apb_watchdog_vmstate = {
|
||||
|
|
|
@ -40,12 +40,14 @@
|
|||
#define WDT_DRIVE_TYPE_MASK (0xFF << 24)
|
||||
#define WDT_PUSH_PULL_MAGIC (0xA8 << 24)
|
||||
#define WDT_OPEN_DRAIN_MAGIC (0x8A << 24)
|
||||
#define WDT_RESET_MASK1 (0x1c / 4)
|
||||
|
||||
#define WDT_TIMEOUT_STATUS (0x10 / 4)
|
||||
#define WDT_TIMEOUT_CLEAR (0x14 / 4)
|
||||
|
||||
#define WDT_RESTART_MAGIC 0x4755
|
||||
|
||||
#define AST2600_SCU_RESET_CONTROL1 (0x40 / 4)
|
||||
#define SCU_RESET_CONTROL1 (0x04 / 4)
|
||||
#define SCU_RESET_SDRAM BIT(0)
|
||||
|
||||
|
@ -54,21 +56,6 @@ static bool aspeed_wdt_is_enabled(const AspeedWDTState *s)
|
|||
return s->regs[WDT_CTRL] & WDT_CTRL_ENABLE;
|
||||
}
|
||||
|
||||
static bool is_ast2500(const AspeedWDTState *s)
|
||||
{
|
||||
switch (s->silicon_rev) {
|
||||
case AST2500_A0_SILICON_REV:
|
||||
case AST2500_A1_SILICON_REV:
|
||||
return true;
|
||||
case AST2400_A0_SILICON_REV:
|
||||
case AST2400_A1_SILICON_REV:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
|
||||
{
|
||||
AspeedWDTState *s = ASPEED_WDT(opaque);
|
||||
|
@ -89,6 +76,8 @@ static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
|
|||
return s->regs[WDT_CTRL];
|
||||
case WDT_RESET_WIDTH:
|
||||
return s->regs[WDT_RESET_WIDTH];
|
||||
case WDT_RESET_MASK1:
|
||||
return s->regs[WDT_RESET_MASK1];
|
||||
case WDT_TIMEOUT_STATUS:
|
||||
case WDT_TIMEOUT_CLEAR:
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
|
@ -124,6 +113,7 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
|
|||
unsigned size)
|
||||
{
|
||||
AspeedWDTState *s = ASPEED_WDT(opaque);
|
||||
AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(s);
|
||||
bool enable = data & WDT_CTRL_ENABLE;
|
||||
|
||||
offset >>= 2;
|
||||
|
@ -140,7 +130,7 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
|
|||
case WDT_RESTART:
|
||||
if ((data & 0xFFFF) == WDT_RESTART_MAGIC) {
|
||||
s->regs[WDT_STATUS] = s->regs[WDT_RELOAD_VALUE];
|
||||
aspeed_wdt_reload(s, !(data & WDT_CTRL_1MHZ_CLK));
|
||||
aspeed_wdt_reload(s, !(s->regs[WDT_CTRL] & WDT_CTRL_1MHZ_CLK));
|
||||
}
|
||||
break;
|
||||
case WDT_CTRL:
|
||||
|
@ -153,24 +143,18 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
|
|||
}
|
||||
break;
|
||||
case WDT_RESET_WIDTH:
|
||||
{
|
||||
uint32_t property = data & WDT_POLARITY_MASK;
|
||||
|
||||
if (property && is_ast2500(s)) {
|
||||
if (property == WDT_ACTIVE_HIGH_MAGIC) {
|
||||
s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_ACTIVE_HIGH;
|
||||
} else if (property == WDT_ACTIVE_LOW_MAGIC) {
|
||||
s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_ACTIVE_HIGH;
|
||||
} else if (property == WDT_PUSH_PULL_MAGIC) {
|
||||
s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_PUSH_PULL;
|
||||
} else if (property == WDT_OPEN_DRAIN_MAGIC) {
|
||||
s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_PUSH_PULL;
|
||||
}
|
||||
if (awc->reset_pulse) {
|
||||
awc->reset_pulse(s, data & WDT_POLARITY_MASK);
|
||||
}
|
||||
s->regs[WDT_RESET_WIDTH] &= ~s->ext_pulse_width_mask;
|
||||
s->regs[WDT_RESET_WIDTH] |= data & s->ext_pulse_width_mask;
|
||||
s->regs[WDT_RESET_WIDTH] &= ~awc->ext_pulse_width_mask;
|
||||
s->regs[WDT_RESET_WIDTH] |= data & awc->ext_pulse_width_mask;
|
||||
break;
|
||||
}
|
||||
|
||||
case WDT_RESET_MASK1:
|
||||
/* TODO: implement */
|
||||
s->regs[WDT_RESET_MASK1] = data;
|
||||
break;
|
||||
|
||||
case WDT_TIMEOUT_STATUS:
|
||||
case WDT_TIMEOUT_CLEAR:
|
||||
qemu_log_mask(LOG_UNIMP,
|
||||
|
@ -226,9 +210,10 @@ static void aspeed_wdt_reset(DeviceState *dev)
|
|||
static void aspeed_wdt_timer_expired(void *dev)
|
||||
{
|
||||
AspeedWDTState *s = ASPEED_WDT(dev);
|
||||
uint32_t reset_ctrl_reg = ASPEED_WDT_GET_CLASS(s)->reset_ctrl_reg;
|
||||
|
||||
/* Do not reset on SDRAM controller reset */
|
||||
if (s->scu->regs[SCU_RESET_CONTROL1] & SCU_RESET_SDRAM) {
|
||||
if (s->scu->regs[reset_ctrl_reg] & SCU_RESET_SDRAM) {
|
||||
timer_del(s->timer);
|
||||
s->regs[WDT_CTRL] = 0;
|
||||
return;
|
||||
|
@ -256,25 +241,6 @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
|
|||
}
|
||||
s->scu = ASPEED_SCU(obj);
|
||||
|
||||
if (!is_supported_silicon_rev(s->silicon_rev)) {
|
||||
error_setg(errp, "Unknown silicon revision: 0x%" PRIx32,
|
||||
s->silicon_rev);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (s->silicon_rev) {
|
||||
case AST2400_A0_SILICON_REV:
|
||||
case AST2400_A1_SILICON_REV:
|
||||
s->ext_pulse_width_mask = 0xff;
|
||||
break;
|
||||
case AST2500_A0_SILICON_REV:
|
||||
case AST2500_A1_SILICON_REV:
|
||||
s->ext_pulse_width_mask = 0xfffff;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, aspeed_wdt_timer_expired, dev);
|
||||
|
||||
/* FIXME: This setting should be derived from the SCU hw strapping
|
||||
|
@ -287,20 +253,15 @@ static void aspeed_wdt_realize(DeviceState *dev, Error **errp)
|
|||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
}
|
||||
|
||||
static Property aspeed_wdt_properties[] = {
|
||||
DEFINE_PROP_UINT32("silicon-rev", AspeedWDTState, silicon_rev, 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void aspeed_wdt_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED Watchdog Controller";
|
||||
dc->realize = aspeed_wdt_realize;
|
||||
dc->reset = aspeed_wdt_reset;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
dc->vmsd = &vmstate_aspeed_wdt;
|
||||
dc->props = aspeed_wdt_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_wdt_info = {
|
||||
|
@ -308,12 +269,88 @@ static const TypeInfo aspeed_wdt_info = {
|
|||
.name = TYPE_ASPEED_WDT,
|
||||
.instance_size = sizeof(AspeedWDTState),
|
||||
.class_init = aspeed_wdt_class_init,
|
||||
.class_size = sizeof(AspeedWDTClass),
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void aspeed_2400_wdt_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedWDTClass *awc = ASPEED_WDT_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2400 Watchdog Controller";
|
||||
awc->offset = 0x20;
|
||||
awc->ext_pulse_width_mask = 0xff;
|
||||
awc->reset_ctrl_reg = SCU_RESET_CONTROL1;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2400_wdt_info = {
|
||||
.name = TYPE_ASPEED_2400_WDT,
|
||||
.parent = TYPE_ASPEED_WDT,
|
||||
.instance_size = sizeof(AspeedWDTState),
|
||||
.class_init = aspeed_2400_wdt_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_2500_wdt_reset_pulse(AspeedWDTState *s, uint32_t property)
|
||||
{
|
||||
if (property) {
|
||||
if (property == WDT_ACTIVE_HIGH_MAGIC) {
|
||||
s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_ACTIVE_HIGH;
|
||||
} else if (property == WDT_ACTIVE_LOW_MAGIC) {
|
||||
s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_ACTIVE_HIGH;
|
||||
} else if (property == WDT_PUSH_PULL_MAGIC) {
|
||||
s->regs[WDT_RESET_WIDTH] |= WDT_RESET_WIDTH_PUSH_PULL;
|
||||
} else if (property == WDT_OPEN_DRAIN_MAGIC) {
|
||||
s->regs[WDT_RESET_WIDTH] &= ~WDT_RESET_WIDTH_PUSH_PULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void aspeed_2500_wdt_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedWDTClass *awc = ASPEED_WDT_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2500 Watchdog Controller";
|
||||
awc->offset = 0x20;
|
||||
awc->ext_pulse_width_mask = 0xfffff;
|
||||
awc->reset_ctrl_reg = SCU_RESET_CONTROL1;
|
||||
awc->reset_pulse = aspeed_2500_wdt_reset_pulse;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2500_wdt_info = {
|
||||
.name = TYPE_ASPEED_2500_WDT,
|
||||
.parent = TYPE_ASPEED_WDT,
|
||||
.instance_size = sizeof(AspeedWDTState),
|
||||
.class_init = aspeed_2500_wdt_class_init,
|
||||
};
|
||||
|
||||
static void aspeed_2600_wdt_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
AspeedWDTClass *awc = ASPEED_WDT_CLASS(klass);
|
||||
|
||||
dc->desc = "ASPEED 2600 Watchdog Controller";
|
||||
awc->offset = 0x40;
|
||||
awc->ext_pulse_width_mask = 0xfffff; /* TODO */
|
||||
awc->reset_ctrl_reg = AST2600_SCU_RESET_CONTROL1;
|
||||
awc->reset_pulse = aspeed_2500_wdt_reset_pulse;
|
||||
}
|
||||
|
||||
static const TypeInfo aspeed_2600_wdt_info = {
|
||||
.name = TYPE_ASPEED_2600_WDT,
|
||||
.parent = TYPE_ASPEED_WDT,
|
||||
.instance_size = sizeof(AspeedWDTState),
|
||||
.class_init = aspeed_2600_wdt_class_init,
|
||||
};
|
||||
|
||||
static void wdt_aspeed_register_types(void)
|
||||
{
|
||||
watchdog_add_model(&model);
|
||||
type_register_static(&aspeed_wdt_info);
|
||||
type_register_static(&aspeed_2400_wdt_info);
|
||||
type_register_static(&aspeed_2500_wdt_info);
|
||||
type_register_static(&aspeed_2600_wdt_info);
|
||||
}
|
||||
|
||||
type_init(wdt_aspeed_register_types)
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#ifndef ASPEED_SOC_H
|
||||
#define ASPEED_SOC_H
|
||||
|
||||
#include "hw/cpu/a15mpcore.h"
|
||||
#include "hw/intc/aspeed_vic.h"
|
||||
#include "hw/misc/aspeed_scu.h"
|
||||
#include "hw/misc/aspeed_sdmc.h"
|
||||
|
@ -24,11 +25,12 @@
|
|||
#include "hw/net/ftgmac100.h"
|
||||
#include "target/arm/cpu.h"
|
||||
#include "hw/gpio/aspeed_gpio.h"
|
||||
#include "hw/sd/aspeed_sdhci.h"
|
||||
|
||||
#define ASPEED_SPIS_NUM 2
|
||||
#define ASPEED_WDTS_NUM 3
|
||||
#define ASPEED_WDTS_NUM 4
|
||||
#define ASPEED_CPUS_NUM 2
|
||||
#define ASPEED_MACS_NUM 2
|
||||
#define ASPEED_MACS_NUM 4
|
||||
|
||||
typedef struct AspeedSoCState {
|
||||
/*< private >*/
|
||||
|
@ -37,6 +39,7 @@ typedef struct AspeedSoCState {
|
|||
/*< public >*/
|
||||
ARMCPU cpu[ASPEED_CPUS_NUM];
|
||||
uint32_t num_cpus;
|
||||
A15MPPrivState a7mpcore;
|
||||
MemoryRegion sram;
|
||||
AspeedVICState vic;
|
||||
AspeedRtcState rtc;
|
||||
|
@ -49,27 +52,28 @@ typedef struct AspeedSoCState {
|
|||
AspeedSDMCState sdmc;
|
||||
AspeedWDTState wdt[ASPEED_WDTS_NUM];
|
||||
FTGMAC100State ftgmac100[ASPEED_MACS_NUM];
|
||||
AspeedMiiState mii[ASPEED_MACS_NUM];
|
||||
AspeedGPIOState gpio;
|
||||
AspeedGPIOState gpio_1_8v;
|
||||
AspeedSDHCIState sdhci;
|
||||
} AspeedSoCState;
|
||||
|
||||
#define TYPE_ASPEED_SOC "aspeed-soc"
|
||||
#define ASPEED_SOC(obj) OBJECT_CHECK(AspeedSoCState, (obj), TYPE_ASPEED_SOC)
|
||||
|
||||
typedef struct AspeedSoCInfo {
|
||||
typedef struct AspeedSoCClass {
|
||||
DeviceClass parent_class;
|
||||
|
||||
const char *name;
|
||||
const char *cpu_type;
|
||||
uint32_t silicon_rev;
|
||||
uint64_t sram_size;
|
||||
int spis_num;
|
||||
int wdts_num;
|
||||
int macs_num;
|
||||
const int *irqmap;
|
||||
const hwaddr *memmap;
|
||||
uint32_t num_cpus;
|
||||
} AspeedSoCInfo;
|
||||
|
||||
typedef struct AspeedSoCClass {
|
||||
DeviceClass parent_class;
|
||||
AspeedSoCInfo *info;
|
||||
} AspeedSoCClass;
|
||||
|
||||
#define ASPEED_SOC_CLASS(klass) \
|
||||
|
@ -92,8 +96,11 @@ enum {
|
|||
ASPEED_SDMC,
|
||||
ASPEED_SCU,
|
||||
ASPEED_ADC,
|
||||
ASPEED_VIDEO,
|
||||
ASPEED_SRAM,
|
||||
ASPEED_SDHCI,
|
||||
ASPEED_GPIO,
|
||||
ASPEED_GPIO_1_8V,
|
||||
ASPEED_RTC,
|
||||
ASPEED_TIMER1,
|
||||
ASPEED_TIMER2,
|
||||
|
@ -110,6 +117,12 @@ enum {
|
|||
ASPEED_I2C,
|
||||
ASPEED_ETH1,
|
||||
ASPEED_ETH2,
|
||||
ASPEED_ETH3,
|
||||
ASPEED_ETH4,
|
||||
ASPEED_MII1,
|
||||
ASPEED_MII2,
|
||||
ASPEED_MII3,
|
||||
ASPEED_MII4,
|
||||
ASPEED_SDRAM,
|
||||
ASPEED_XDMA,
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "hw/sd/sdhci.h"
|
||||
#include "hw/sd/bcm2835_sdhost.h"
|
||||
#include "hw/gpio/bcm2835_gpio.h"
|
||||
#include "hw/misc/unimp.h"
|
||||
|
||||
#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
|
||||
#define BCM2835_PERIPHERALS(obj) \
|
||||
|
@ -37,6 +38,10 @@ typedef struct BCM2835PeripheralState {
|
|||
MemoryRegion ram_alias[4];
|
||||
qemu_irq irq, fiq;
|
||||
|
||||
UnimplementedDeviceState systmr;
|
||||
UnimplementedDeviceState armtmr;
|
||||
UnimplementedDeviceState cprman;
|
||||
UnimplementedDeviceState a2w;
|
||||
PL011State uart0;
|
||||
BCM2835AuxState aux;
|
||||
BCM2835FBState fb;
|
||||
|
@ -48,6 +53,16 @@ typedef struct BCM2835PeripheralState {
|
|||
SDHCIState sdhci;
|
||||
BCM2835SDHostState sdhost;
|
||||
BCM2835GpioState gpio;
|
||||
UnimplementedDeviceState i2s;
|
||||
UnimplementedDeviceState spi[1];
|
||||
UnimplementedDeviceState i2c[3];
|
||||
UnimplementedDeviceState otp;
|
||||
UnimplementedDeviceState dbus;
|
||||
UnimplementedDeviceState ave0;
|
||||
UnimplementedDeviceState bscsl;
|
||||
UnimplementedDeviceState smi;
|
||||
UnimplementedDeviceState dwc2;
|
||||
UnimplementedDeviceState sdramc;
|
||||
} BCM2835PeripheralState;
|
||||
|
||||
#endif /* BCM2835_PERIPHERALS_H */
|
||||
|
|
|
@ -25,8 +25,7 @@
|
|||
#ifndef HW_ARM_RASPI_PLATFORM_H
|
||||
#define HW_ARM_RASPI_PLATFORM_H
|
||||
|
||||
#define MCORE_OFFSET 0x0000 /* Fake frame buffer device
|
||||
* (the multicore sync block) */
|
||||
#define MSYNC_OFFSET 0x0000 /* Multicore Sync Block */
|
||||
#define IC0_OFFSET 0x2000
|
||||
#define ST_OFFSET 0x3000 /* System Timer */
|
||||
#define MPHI_OFFSET 0x6000 /* Message-based Parallel Host Intf. */
|
||||
|
@ -37,9 +36,10 @@
|
|||
#define ARMCTRL_TIMER0_1_OFFSET (ARM_OFFSET + 0x400) /* Timer 0 and 1 */
|
||||
#define ARMCTRL_0_SBM_OFFSET (ARM_OFFSET + 0x800) /* User 0 (ARM) Semaphores
|
||||
* Doorbells & Mailboxes */
|
||||
#define PM_OFFSET 0x100000 /* Power Management, Reset controller
|
||||
* and Watchdog registers */
|
||||
#define PCM_CLOCK_OFFSET 0x101098
|
||||
#define CPRMAN_OFFSET 0x100000 /* Power Management, Watchdog */
|
||||
#define CM_OFFSET 0x101000 /* Clock Management */
|
||||
#define A2W_OFFSET 0x102000 /* Reset controller */
|
||||
#define AVS_OFFSET 0x103000 /* Audio Video Standard */
|
||||
#define RNG_OFFSET 0x104000
|
||||
#define GPIO_OFFSET 0x200000
|
||||
#define UART0_OFFSET 0x201000
|
||||
|
@ -47,11 +47,17 @@
|
|||
#define I2S_OFFSET 0x203000
|
||||
#define SPI0_OFFSET 0x204000
|
||||
#define BSC0_OFFSET 0x205000 /* BSC0 I2C/TWI */
|
||||
#define UART1_OFFSET 0x215000
|
||||
#define EMMC_OFFSET 0x300000
|
||||
#define OTP_OFFSET 0x20f000
|
||||
#define BSC_SL_OFFSET 0x214000 /* SPI slave */
|
||||
#define AUX_OFFSET 0x215000 /* AUX: UART1/SPI1/SPI2 */
|
||||
#define EMMC1_OFFSET 0x300000
|
||||
#define SMI_OFFSET 0x600000
|
||||
#define BSC1_OFFSET 0x804000 /* BSC1 I2C/TWI */
|
||||
#define USB_OFFSET 0x980000 /* DTC_OTG USB controller */
|
||||
#define BSC2_OFFSET 0x805000 /* BSC2 I2C/TWI */
|
||||
#define DBUS_OFFSET 0x900000
|
||||
#define AVE0_OFFSET 0x910000
|
||||
#define USB_OTG_OFFSET 0x980000 /* DTC_OTG USB controller */
|
||||
#define SDRAMC_OFFSET 0xe00000
|
||||
#define DMA15_OFFSET 0xE05000 /* DMA controller, channel 15 */
|
||||
|
||||
/* GPU interrupts */
|
||||
|
@ -112,7 +118,7 @@
|
|||
#define INTERRUPT_SPI 54
|
||||
#define INTERRUPT_I2SPCM 55
|
||||
#define INTERRUPT_SDIO 56
|
||||
#define INTERRUPT_UART 57
|
||||
#define INTERRUPT_UART0 57
|
||||
#define INTERRUPT_SLIMBUS 58
|
||||
#define INTERRUPT_VEC 59
|
||||
#define INTERRUPT_CPG 60
|
||||
|
|
|
@ -25,10 +25,13 @@
|
|||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_ASPEED_I2C "aspeed.i2c"
|
||||
#define TYPE_ASPEED_2400_I2C TYPE_ASPEED_I2C "-ast2400"
|
||||
#define TYPE_ASPEED_2500_I2C TYPE_ASPEED_I2C "-ast2500"
|
||||
#define TYPE_ASPEED_2600_I2C TYPE_ASPEED_I2C "-ast2600"
|
||||
#define ASPEED_I2C(obj) \
|
||||
OBJECT_CHECK(AspeedI2CState, (obj), TYPE_ASPEED_I2C)
|
||||
|
||||
#define ASPEED_I2C_NR_BUSSES 14
|
||||
#define ASPEED_I2C_NR_BUSSES 16
|
||||
|
||||
struct AspeedI2CState;
|
||||
|
||||
|
@ -39,6 +42,7 @@ typedef struct AspeedI2CBus {
|
|||
|
||||
I2CBus *bus;
|
||||
uint8_t id;
|
||||
qemu_irq irq;
|
||||
|
||||
uint32_t ctrl;
|
||||
uint32_t timing[2];
|
||||
|
@ -59,6 +63,20 @@ typedef struct AspeedI2CState {
|
|||
AspeedI2CBus busses[ASPEED_I2C_NR_BUSSES];
|
||||
} AspeedI2CState;
|
||||
|
||||
#define ASPEED_I2C_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(AspeedI2CClass, (klass), TYPE_ASPEED_I2C)
|
||||
#define ASPEED_I2C_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(AspeedI2CClass, (obj), TYPE_ASPEED_I2C)
|
||||
|
||||
typedef struct AspeedI2CClass {
|
||||
SysBusDeviceClass parent_class;
|
||||
|
||||
uint8_t num_busses;
|
||||
uint8_t reg_size;
|
||||
uint8_t gap;
|
||||
qemu_irq (*bus_get_irq)(AspeedI2CBus *);
|
||||
} AspeedI2CClass;
|
||||
|
||||
I2CBus *aspeed_i2c_get_bus(DeviceState *dev, int busnr);
|
||||
|
||||
#endif /* ASPEED_I2C_H */
|
||||
|
|
|
@ -17,8 +17,10 @@
|
|||
#define ASPEED_SCU(obj) OBJECT_CHECK(AspeedSCUState, (obj), TYPE_ASPEED_SCU)
|
||||
#define TYPE_ASPEED_2400_SCU TYPE_ASPEED_SCU "-ast2400"
|
||||
#define TYPE_ASPEED_2500_SCU TYPE_ASPEED_SCU "-ast2500"
|
||||
#define TYPE_ASPEED_2600_SCU TYPE_ASPEED_SCU "-ast2600"
|
||||
|
||||
#define ASPEED_SCU_NR_REGS (0x1A8 >> 2)
|
||||
#define ASPEED_AST2600_SCU_NR_REGS (0xE20 >> 2)
|
||||
|
||||
typedef struct AspeedSCUState {
|
||||
/*< private >*/
|
||||
|
@ -27,7 +29,7 @@ typedef struct AspeedSCUState {
|
|||
/*< public >*/
|
||||
MemoryRegion iomem;
|
||||
|
||||
uint32_t regs[ASPEED_SCU_NR_REGS];
|
||||
uint32_t regs[ASPEED_AST2600_SCU_NR_REGS];
|
||||
uint32_t silicon_rev;
|
||||
uint32_t hw_strap1;
|
||||
uint32_t hw_strap2;
|
||||
|
@ -38,6 +40,7 @@ typedef struct AspeedSCUState {
|
|||
#define AST2400_A1_SILICON_REV 0x02010303U
|
||||
#define AST2500_A0_SILICON_REV 0x04000303U
|
||||
#define AST2500_A1_SILICON_REV 0x04010303U
|
||||
#define AST2600_A0_SILICON_REV 0x05000303U
|
||||
|
||||
#define ASPEED_IS_AST2500(si_rev) ((((si_rev) >> 24) & 0xff) == 0x04)
|
||||
|
||||
|
@ -54,6 +57,8 @@ typedef struct AspeedSCUClass {
|
|||
const uint32_t *resets;
|
||||
uint32_t (*calc_hpll)(AspeedSCUState *s, uint32_t hpll_reg);
|
||||
uint32_t apb_divider;
|
||||
uint32_t nr_regs;
|
||||
const MemoryRegionOps *ops;
|
||||
} AspeedSCUClass;
|
||||
|
||||
#define ASPEED_SCU_PROT_KEY 0x1688A8A8
|
||||
|
|
|
@ -13,6 +13,9 @@
|
|||
|
||||
#define TYPE_ASPEED_SDMC "aspeed.sdmc"
|
||||
#define ASPEED_SDMC(obj) OBJECT_CHECK(AspeedSDMCState, (obj), TYPE_ASPEED_SDMC)
|
||||
#define TYPE_ASPEED_2400_SDMC TYPE_ASPEED_SDMC "-ast2400"
|
||||
#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)
|
||||
|
||||
|
@ -24,12 +27,21 @@ typedef struct AspeedSDMCState {
|
|||
MemoryRegion iomem;
|
||||
|
||||
uint32_t regs[ASPEED_SDMC_NR_REGS];
|
||||
uint32_t silicon_rev;
|
||||
uint32_t ram_bits;
|
||||
uint64_t ram_size;
|
||||
uint64_t max_ram_size;
|
||||
uint32_t fixed_conf;
|
||||
|
||||
} AspeedSDMCState;
|
||||
|
||||
#define ASPEED_SDMC_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(AspeedSDMCClass, (klass), TYPE_ASPEED_SDMC)
|
||||
#define ASPEED_SDMC_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(AspeedSDMCClass, (obj), TYPE_ASPEED_SDMC)
|
||||
|
||||
typedef struct AspeedSDMCClass {
|
||||
SysBusDeviceClass parent_class;
|
||||
|
||||
uint64_t max_ram_size;
|
||||
uint32_t (*compute_conf)(AspeedSDMCState *s, uint32_t data);
|
||||
void (*write)(AspeedSDMCState *s, uint32_t reg, uint32_t data);
|
||||
} AspeedSDMCClass;
|
||||
|
||||
#endif /* ASPEED_SDMC_H */
|
||||
|
|
|
@ -66,4 +66,21 @@ typedef struct FTGMAC100State {
|
|||
uint32_t rxdes0_edorr;
|
||||
} FTGMAC100State;
|
||||
|
||||
#define TYPE_ASPEED_MII "aspeed-mmi"
|
||||
#define ASPEED_MII(obj) OBJECT_CHECK(AspeedMiiState, (obj), TYPE_ASPEED_MII)
|
||||
|
||||
/*
|
||||
* AST2600 MII controller
|
||||
*/
|
||||
typedef struct AspeedMiiState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
FTGMAC100State *nic;
|
||||
|
||||
MemoryRegion iomem;
|
||||
uint32_t phycr;
|
||||
uint32_t phydata;
|
||||
} AspeedMiiState;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -72,7 +72,7 @@
|
|||
* ptimer_set_count() or ptimer_set_limit() will not trigger the timer
|
||||
* (though it will cause a reload). Only a counter decrement to "0"
|
||||
* will cause a trigger. Not compatible with NO_IMMEDIATE_TRIGGER;
|
||||
* ptimer_init() will assert() that you don't set both.
|
||||
* ptimer_init_with_bh() will assert() that you don't set both.
|
||||
*/
|
||||
#define PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT (1 << 5)
|
||||
|
||||
|
@ -81,7 +81,7 @@ typedef struct ptimer_state ptimer_state;
|
|||
typedef void (*ptimer_cb)(void *opaque);
|
||||
|
||||
/**
|
||||
* ptimer_init - Allocate and return a new ptimer
|
||||
* ptimer_init_with_bh - Allocate and return a new ptimer
|
||||
* @bh: QEMU bottom half which is run on timer expiry
|
||||
* @policy: PTIMER_POLICY_* bits specifying behaviour
|
||||
*
|
||||
|
@ -89,17 +89,71 @@ typedef void (*ptimer_cb)(void *opaque);
|
|||
* The ptimer takes ownership of @bh and will delete it
|
||||
* when the ptimer is eventually freed.
|
||||
*/
|
||||
ptimer_state *ptimer_init(QEMUBH *bh, uint8_t policy_mask);
|
||||
ptimer_state *ptimer_init_with_bh(QEMUBH *bh, uint8_t policy_mask);
|
||||
|
||||
/**
|
||||
* ptimer_init - Allocate and return a new ptimer
|
||||
* @callback: function to call on ptimer expiry
|
||||
* @callback_opaque: opaque pointer passed to @callback
|
||||
* @policy: PTIMER_POLICY_* bits specifying behaviour
|
||||
*
|
||||
* The ptimer returned must be freed using ptimer_free().
|
||||
*
|
||||
* If a ptimer is created using this API then will use the
|
||||
* transaction-based API for modifying ptimer state: all calls
|
||||
* to functions which modify ptimer state:
|
||||
* - ptimer_set_period()
|
||||
* - ptimer_set_freq()
|
||||
* - ptimer_set_limit()
|
||||
* - ptimer_set_count()
|
||||
* - ptimer_run()
|
||||
* - ptimer_stop()
|
||||
* must be between matched calls to ptimer_transaction_begin()
|
||||
* and ptimer_transaction_commit(). When ptimer_transaction_commit()
|
||||
* is called it will evaluate the state of the timer after all the
|
||||
* changes in the transaction, and call the callback if necessary.
|
||||
*
|
||||
* The callback function is always called from within a transaction
|
||||
* begin/commit block, so the callback should not call the
|
||||
* ptimer_transaction_begin() function itself. If the callback changes
|
||||
* the ptimer state such that another ptimer expiry is triggered, then
|
||||
* the callback will be called a second time after the first call returns.
|
||||
*/
|
||||
ptimer_state *ptimer_init(ptimer_cb callback,
|
||||
void *callback_opaque,
|
||||
uint8_t policy_mask);
|
||||
|
||||
/**
|
||||
* ptimer_free - Free a ptimer
|
||||
* @s: timer to free
|
||||
*
|
||||
* Free a ptimer created using ptimer_init() (including
|
||||
* Free a ptimer created using ptimer_init_with_bh() (including
|
||||
* deleting the bottom half which it is using).
|
||||
*/
|
||||
void ptimer_free(ptimer_state *s);
|
||||
|
||||
/**
|
||||
* ptimer_transaction_begin() - Start a ptimer modification transaction
|
||||
*
|
||||
* This function must be called before making any calls to functions
|
||||
* which modify the ptimer's state (see the ptimer_init() documentation
|
||||
* for a list of these), and must always have a matched call to
|
||||
* ptimer_transaction_commit().
|
||||
* It is an error to call this function for a BH-based ptimer;
|
||||
* attempting to do this will trigger an assert.
|
||||
*/
|
||||
void ptimer_transaction_begin(ptimer_state *s);
|
||||
|
||||
/**
|
||||
* ptimer_transaction_commit() - Commit a ptimer modification transaction
|
||||
*
|
||||
* This function must be called after calls to functions which modify
|
||||
* the ptimer's state, and completes the update of the ptimer. If the
|
||||
* ptimer state now means that we should trigger the timer expiry
|
||||
* callback, it will be called directly.
|
||||
*/
|
||||
void ptimer_transaction_commit(ptimer_state *s);
|
||||
|
||||
/**
|
||||
* ptimer_set_period - Set counter increment interval in nanoseconds
|
||||
* @s: ptimer to configure
|
||||
|
@ -108,6 +162,9 @@ void ptimer_free(ptimer_state *s);
|
|||
* Note that if your counter behaviour is specified as having a
|
||||
* particular frequency rather than a period then ptimer_set_freq()
|
||||
* may be more appropriate.
|
||||
*
|
||||
* This function will assert if it is called outside a
|
||||
* ptimer_transaction_begin/commit block, unless this is a bottom-half ptimer.
|
||||
*/
|
||||
void ptimer_set_period(ptimer_state *s, int64_t period);
|
||||
|
||||
|
@ -121,6 +178,9 @@ void ptimer_set_period(ptimer_state *s, int64_t period);
|
|||
* as setting the frequency then this function is more appropriate,
|
||||
* because it allows specifying an effective period which is
|
||||
* precise to fractions of a nanosecond, avoiding rounding errors.
|
||||
*
|
||||
* This function will assert if it is called outside a
|
||||
* ptimer_transaction_begin/commit block, unless this is a bottom-half ptimer.
|
||||
*/
|
||||
void ptimer_set_freq(ptimer_state *s, uint32_t freq);
|
||||
|
||||
|
@ -148,6 +208,9 @@ uint64_t ptimer_get_limit(ptimer_state *s);
|
|||
* Set the limit value of the down-counter. The @reload flag can
|
||||
* be used to emulate the behaviour of timers which immediately
|
||||
* reload the counter when their reload register is written to.
|
||||
*
|
||||
* This function will assert if it is called outside a
|
||||
* ptimer_transaction_begin/commit block, unless this is a bottom-half ptimer.
|
||||
*/
|
||||
void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload);
|
||||
|
||||
|
@ -169,6 +232,9 @@ uint64_t ptimer_get_count(ptimer_state *s);
|
|||
* Set the value of the down-counter. If the counter is currently
|
||||
* enabled this will arrange for a timer callback at the appropriate
|
||||
* point in the future.
|
||||
*
|
||||
* This function will assert if it is called outside a
|
||||
* ptimer_transaction_begin/commit block, unless this is a bottom-half ptimer.
|
||||
*/
|
||||
void ptimer_set_count(ptimer_state *s, uint64_t count);
|
||||
|
||||
|
@ -178,10 +244,14 @@ void ptimer_set_count(ptimer_state *s, uint64_t count);
|
|||
* @oneshot: non-zero if this timer should only count down once
|
||||
*
|
||||
* Start a ptimer counting down; when it reaches zero the bottom half
|
||||
* passed to ptimer_init() will be invoked. If the @oneshot argument is zero,
|
||||
* passed to ptimer_init_with_bh() will be invoked.
|
||||
* If the @oneshot argument is zero,
|
||||
* the counter value will then be reloaded from the limit and it will
|
||||
* start counting down again. If @oneshot is non-zero, then the counter
|
||||
* will disable itself when it reaches zero.
|
||||
*
|
||||
* This function will assert if it is called outside a
|
||||
* ptimer_transaction_begin/commit block, unless this is a bottom-half ptimer.
|
||||
*/
|
||||
void ptimer_run(ptimer_state *s, int oneshot);
|
||||
|
||||
|
@ -194,6 +264,9 @@ void ptimer_run(ptimer_state *s, int oneshot);
|
|||
*
|
||||
* Note that this can cause it to "lose" time, even if it is immediately
|
||||
* restarted.
|
||||
*
|
||||
* This function will assert if it is called outside a
|
||||
* ptimer_transaction_begin/commit block, unless this is a bottom-half ptimer.
|
||||
*/
|
||||
void ptimer_stop(ptimer_state *s);
|
||||
|
||||
|
|
34
include/hw/sd/aspeed_sdhci.h
Normal file
34
include/hw/sd/aspeed_sdhci.h
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Aspeed SD Host Controller
|
||||
* Eddie James <eajames@linux.ibm.com>
|
||||
*
|
||||
* Copyright (C) 2019 IBM Corp
|
||||
* SPDX-License-Identifer: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef ASPEED_SDHCI_H
|
||||
#define ASPEED_SDHCI_H
|
||||
|
||||
#include "hw/sd/sdhci.h"
|
||||
|
||||
#define TYPE_ASPEED_SDHCI "aspeed.sdhci"
|
||||
#define ASPEED_SDHCI(obj) OBJECT_CHECK(AspeedSDHCIState, (obj), \
|
||||
TYPE_ASPEED_SDHCI)
|
||||
|
||||
#define ASPEED_SDHCI_CAPABILITIES 0x01E80080
|
||||
#define ASPEED_SDHCI_NUM_SLOTS 2
|
||||
#define ASPEED_SDHCI_NUM_REGS (ASPEED_SDHCI_REG_SIZE / sizeof(uint32_t))
|
||||
#define ASPEED_SDHCI_REG_SIZE 0x100
|
||||
|
||||
typedef struct AspeedSDHCIState {
|
||||
SysBusDevice parent;
|
||||
|
||||
SDHCIState slots[ASPEED_SDHCI_NUM_SLOTS];
|
||||
|
||||
MemoryRegion iomem;
|
||||
qemu_irq irq;
|
||||
|
||||
uint32_t regs[ASPEED_SDHCI_NUM_REGS];
|
||||
} AspeedSDHCIState;
|
||||
|
||||
#endif /* ASPEED_SDHCI_H */
|
|
@ -49,6 +49,10 @@ typedef struct AspeedSMCController {
|
|||
hwaddr dma_flash_mask;
|
||||
hwaddr dma_dram_mask;
|
||||
uint32_t nregs;
|
||||
uint32_t (*segment_to_reg)(const struct AspeedSMCState *s,
|
||||
const AspeedSegments *seg);
|
||||
void (*reg_to_segment)(const struct AspeedSMCState *s, uint32_t reg,
|
||||
AspeedSegments *seg);
|
||||
} AspeedSMCController;
|
||||
|
||||
typedef struct AspeedSMCFlash {
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
#define ASPEED_TIMER(obj) \
|
||||
OBJECT_CHECK(AspeedTimerCtrlState, (obj), TYPE_ASPEED_TIMER);
|
||||
#define TYPE_ASPEED_TIMER "aspeed.timer"
|
||||
#define TYPE_ASPEED_2400_TIMER TYPE_ASPEED_TIMER "-ast2400"
|
||||
#define TYPE_ASPEED_2500_TIMER TYPE_ASPEED_TIMER "-ast2500"
|
||||
#define TYPE_ASPEED_2600_TIMER TYPE_ASPEED_TIMER "-ast2600"
|
||||
|
||||
#define ASPEED_TIMER_NR_TIMERS 8
|
||||
|
||||
typedef struct AspeedTimer {
|
||||
|
@ -55,9 +59,23 @@ typedef struct AspeedTimerCtrlState {
|
|||
|
||||
uint32_t ctrl;
|
||||
uint32_t ctrl2;
|
||||
uint32_t ctrl3;
|
||||
uint32_t irq_sts;
|
||||
AspeedTimer timers[ASPEED_TIMER_NR_TIMERS];
|
||||
|
||||
AspeedSCUState *scu;
|
||||
} AspeedTimerCtrlState;
|
||||
|
||||
#define ASPEED_TIMER_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(AspeedTimerClass, (klass), TYPE_ASPEED_TIMER)
|
||||
#define ASPEED_TIMER_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(AspeedTimerClass, (obj), TYPE_ASPEED_TIMER)
|
||||
|
||||
typedef struct AspeedTimerClass {
|
||||
SysBusDeviceClass parent_class;
|
||||
|
||||
uint64_t (*read)(AspeedTimerCtrlState *s, hwaddr offset);
|
||||
void (*write)(AspeedTimerCtrlState *s, hwaddr offset, uint64_t value);
|
||||
} AspeedTimerClass;
|
||||
|
||||
#endif /* ASPEED_TIMER_H */
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#define R_TIM1_MAX 6
|
||||
|
||||
struct Msf2Timer {
|
||||
QEMUBH *bh;
|
||||
ptimer_state *ptimer;
|
||||
|
||||
uint32_t regs[R_TIM1_MAX];
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
#define TYPE_ASPEED_WDT "aspeed.wdt"
|
||||
#define ASPEED_WDT(obj) \
|
||||
OBJECT_CHECK(AspeedWDTState, (obj), TYPE_ASPEED_WDT)
|
||||
#define TYPE_ASPEED_2400_WDT TYPE_ASPEED_WDT "-ast2400"
|
||||
#define TYPE_ASPEED_2500_WDT TYPE_ASPEED_WDT "-ast2500"
|
||||
#define TYPE_ASPEED_2600_WDT TYPE_ASPEED_WDT "-ast2600"
|
||||
|
||||
#define ASPEED_WDT_REGS_MAX (0x20 / 4)
|
||||
|
||||
|
@ -30,8 +33,20 @@ typedef struct AspeedWDTState {
|
|||
|
||||
AspeedSCUState *scu;
|
||||
uint32_t pclk_freq;
|
||||
uint32_t silicon_rev;
|
||||
uint32_t ext_pulse_width_mask;
|
||||
} AspeedWDTState;
|
||||
|
||||
#define ASPEED_WDT_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(AspeedWDTClass, (klass), TYPE_ASPEED_WDT)
|
||||
#define ASPEED_WDT_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(AspeedWDTClass, (obj), TYPE_ASPEED_WDT)
|
||||
|
||||
typedef struct AspeedWDTClass {
|
||||
SysBusDeviceClass parent_class;
|
||||
|
||||
uint32_t offset;
|
||||
uint32_t ext_pulse_width_mask;
|
||||
uint32_t reset_ctrl_reg;
|
||||
void (*reset_pulse)(AspeedWDTState *s, uint32_t property);
|
||||
} AspeedWDTClass;
|
||||
|
||||
#endif /* WDT_ASPEED_H */
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
#define XLF_EFI_HANDOVER_32 (1<<2)
|
||||
#define XLF_EFI_HANDOVER_64 (1<<3)
|
||||
#define XLF_EFI_KEXEC (1<<4)
|
||||
#define XLF_5LEVEL (1<<5)
|
||||
#define XLF_5LEVEL_ENABLED (1<<6)
|
||||
|
||||
|
||||
#endif /* _ASM_X86_BOOTPARAM_H */
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#define KVM_FEATURE_ASYNC_PF_VMEXIT 10
|
||||
#define KVM_FEATURE_PV_SEND_IPI 11
|
||||
#define KVM_FEATURE_POLL_CONTROL 12
|
||||
#define KVM_FEATURE_PV_SCHED_YIELD 13
|
||||
|
||||
#define KVM_HINTS_REALTIME 0
|
||||
|
||||
|
|
|
@ -259,10 +259,32 @@ struct ethtool_tunable {
|
|||
#define ETHTOOL_PHY_FAST_LINK_DOWN_ON 0
|
||||
#define ETHTOOL_PHY_FAST_LINK_DOWN_OFF 0xff
|
||||
|
||||
/* Energy Detect Power Down (EDPD) is a feature supported by some PHYs, where
|
||||
* the PHY's RX & TX blocks are put into a low-power mode when there is no
|
||||
* link detected (typically cable is un-plugged). For RX, only a minimal
|
||||
* link-detection is available, and for TX the PHY wakes up to send link pulses
|
||||
* to avoid any lock-ups in case the peer PHY may also be running in EDPD mode.
|
||||
*
|
||||
* Some PHYs may support configuration of the wake-up interval for TX pulses,
|
||||
* and some PHYs may support only disabling TX pulses entirely. For the latter
|
||||
* a special value is required (ETHTOOL_PHY_EDPD_NO_TX) so that this can be
|
||||
* configured from userspace (should the user want it).
|
||||
*
|
||||
* The interval units for TX wake-up are in milliseconds, since this should
|
||||
* cover a reasonable range of intervals:
|
||||
* - from 1 millisecond, which does not sound like much of a power-saver
|
||||
* - to ~65 seconds which is quite a lot to wait for a link to come up when
|
||||
* plugging a cable
|
||||
*/
|
||||
#define ETHTOOL_PHY_EDPD_DFLT_TX_MSECS 0xffff
|
||||
#define ETHTOOL_PHY_EDPD_NO_TX 0xfffe
|
||||
#define ETHTOOL_PHY_EDPD_DISABLE 0
|
||||
|
||||
enum phy_tunable_id {
|
||||
ETHTOOL_PHY_ID_UNSPEC,
|
||||
ETHTOOL_PHY_DOWNSHIFT,
|
||||
ETHTOOL_PHY_FAST_LINK_DOWN,
|
||||
ETHTOOL_PHY_EDPD,
|
||||
/*
|
||||
* Add your fresh new phy tunable attribute above and remember to update
|
||||
* phy_tunable_strings[] in net/core/ethtool.c
|
||||
|
@ -1483,6 +1505,8 @@ enum ethtool_link_mode_bit_indices {
|
|||
ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT = 64,
|
||||
ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT = 65,
|
||||
ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT = 66,
|
||||
ETHTOOL_LINK_MODE_100baseT1_Full_BIT = 67,
|
||||
ETHTOOL_LINK_MODE_1000baseT1_Full_BIT = 68,
|
||||
|
||||
/* must be last entry */
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS
|
||||
|
|
|
@ -528,6 +528,7 @@
|
|||
#define PCI_EXP_LNKCAP_SLS_5_0GB 0x00000002 /* LNKCAP2 SLS Vector bit 1 */
|
||||
#define PCI_EXP_LNKCAP_SLS_8_0GB 0x00000003 /* LNKCAP2 SLS Vector bit 2 */
|
||||
#define PCI_EXP_LNKCAP_SLS_16_0GB 0x00000004 /* LNKCAP2 SLS Vector bit 3 */
|
||||
#define PCI_EXP_LNKCAP_SLS_32_0GB 0x00000005 /* LNKCAP2 SLS Vector bit 4 */
|
||||
#define PCI_EXP_LNKCAP_MLW 0x000003f0 /* Maximum Link Width */
|
||||
#define PCI_EXP_LNKCAP_ASPMS 0x00000c00 /* ASPM Support */
|
||||
#define PCI_EXP_LNKCAP_L0SEL 0x00007000 /* L0s Exit Latency */
|
||||
|
@ -556,6 +557,7 @@
|
|||
#define PCI_EXP_LNKSTA_CLS_5_0GB 0x0002 /* Current Link Speed 5.0GT/s */
|
||||
#define PCI_EXP_LNKSTA_CLS_8_0GB 0x0003 /* Current Link Speed 8.0GT/s */
|
||||
#define PCI_EXP_LNKSTA_CLS_16_0GB 0x0004 /* Current Link Speed 16.0GT/s */
|
||||
#define PCI_EXP_LNKSTA_CLS_32_0GB 0x0005 /* Current Link Speed 32.0GT/s */
|
||||
#define PCI_EXP_LNKSTA_NLW 0x03f0 /* Negotiated Link Width */
|
||||
#define PCI_EXP_LNKSTA_NLW_X1 0x0010 /* Current Link Width x1 */
|
||||
#define PCI_EXP_LNKSTA_NLW_X2 0x0020 /* Current Link Width x2 */
|
||||
|
@ -589,6 +591,7 @@
|
|||
#define PCI_EXP_SLTCTL_CCIE 0x0010 /* Command Completed Interrupt Enable */
|
||||
#define PCI_EXP_SLTCTL_HPIE 0x0020 /* Hot-Plug Interrupt Enable */
|
||||
#define PCI_EXP_SLTCTL_AIC 0x00c0 /* Attention Indicator Control */
|
||||
#define PCI_EXP_SLTCTL_ATTN_IND_SHIFT 6 /* Attention Indicator shift */
|
||||
#define PCI_EXP_SLTCTL_ATTN_IND_ON 0x0040 /* Attention Indicator on */
|
||||
#define PCI_EXP_SLTCTL_ATTN_IND_BLINK 0x0080 /* Attention Indicator blinking */
|
||||
#define PCI_EXP_SLTCTL_ATTN_IND_OFF 0x00c0 /* Attention Indicator off */
|
||||
|
@ -661,6 +664,7 @@
|
|||
#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x00000004 /* Supported Speed 5GT/s */
|
||||
#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x00000008 /* Supported Speed 8GT/s */
|
||||
#define PCI_EXP_LNKCAP2_SLS_16_0GB 0x00000010 /* Supported Speed 16GT/s */
|
||||
#define PCI_EXP_LNKCAP2_SLS_32_0GB 0x00000020 /* Supported Speed 32GT/s */
|
||||
#define PCI_EXP_LNKCAP2_CROSSLINK 0x00000100 /* Crosslink supported */
|
||||
#define PCI_EXP_LNKCTL2 48 /* Link Control 2 */
|
||||
#define PCI_EXP_LNKCTL2_TLS 0x000f
|
||||
|
@ -668,6 +672,7 @@
|
|||
#define PCI_EXP_LNKCTL2_TLS_5_0GT 0x0002 /* Supported Speed 5GT/s */
|
||||
#define PCI_EXP_LNKCTL2_TLS_8_0GT 0x0003 /* Supported Speed 8GT/s */
|
||||
#define PCI_EXP_LNKCTL2_TLS_16_0GT 0x0004 /* Supported Speed 16GT/s */
|
||||
#define PCI_EXP_LNKCTL2_TLS_32_0GT 0x0005 /* Supported Speed 32GT/s */
|
||||
#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */
|
||||
#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 52 /* v2 endpoints with link end here */
|
||||
#define PCI_EXP_SLTCAP2 52 /* Slot Capabilities 2 */
|
||||
|
@ -709,7 +714,9 @@
|
|||
#define PCI_EXT_CAP_ID_DPC 0x1D /* Downstream Port Containment */
|
||||
#define PCI_EXT_CAP_ID_L1SS 0x1E /* L1 PM Substates */
|
||||
#define PCI_EXT_CAP_ID_PTM 0x1F /* Precision Time Measurement */
|
||||
#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PTM
|
||||
#define PCI_EXT_CAP_ID_DLF 0x25 /* Data Link Feature */
|
||||
#define PCI_EXT_CAP_ID_PL_16GT 0x26 /* Physical Layer 16.0 GT/s */
|
||||
#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PL_16GT
|
||||
|
||||
#define PCI_EXT_CAP_DSN_SIZEOF 12
|
||||
#define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40
|
||||
|
@ -1049,4 +1056,14 @@
|
|||
#define PCI_L1SS_CTL1_LTR_L12_TH_SCALE 0xe0000000 /* LTR_L1.2_THRESHOLD_Scale */
|
||||
#define PCI_L1SS_CTL2 0x0c /* Control 2 Register */
|
||||
|
||||
/* Data Link Feature */
|
||||
#define PCI_DLF_CAP 0x04 /* Capabilities Register */
|
||||
#define PCI_DLF_EXCHANGE_ENABLE 0x80000000 /* Data Link Feature Exchange Enable */
|
||||
|
||||
/* Physical Layer 16.0 GT/s */
|
||||
#define PCI_PL_16GT_LE_CTRL 0x20 /* Lane Equalization Control Register */
|
||||
#define PCI_PL_16GT_LE_CTRL_DSP_TX_PRESET_MASK 0x0000000F
|
||||
#define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_MASK 0x000000F0
|
||||
#define PCI_PL_16GT_LE_CTRL_USP_TX_PRESET_SHIFT 4
|
||||
|
||||
#endif /* LINUX_PCI_REGS_H */
|
||||
|
|
19
include/standard-headers/linux/virtio_fs.h
Normal file
19
include/standard-headers/linux/virtio_fs.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
|
||||
|
||||
#ifndef _LINUX_VIRTIO_FS_H
|
||||
#define _LINUX_VIRTIO_FS_H
|
||||
|
||||
#include "standard-headers/linux/types.h"
|
||||
#include "standard-headers/linux/virtio_ids.h"
|
||||
#include "standard-headers/linux/virtio_config.h"
|
||||
#include "standard-headers/linux/virtio_types.h"
|
||||
|
||||
struct virtio_fs_config {
|
||||
/* Filesystem name (UTF-8, not NUL-terminated, padded with NULs) */
|
||||
uint8_t tag[36];
|
||||
|
||||
/* Number of request queues */
|
||||
uint32_t num_request_queues;
|
||||
} QEMU_PACKED;
|
||||
|
||||
#endif /* _LINUX_VIRTIO_FS_H */
|
|
@ -43,6 +43,8 @@
|
|||
#define VIRTIO_ID_INPUT 18 /* virtio input */
|
||||
#define VIRTIO_ID_VSOCK 19 /* virtio vsock transport */
|
||||
#define VIRTIO_ID_CRYPTO 20 /* virtio crypto */
|
||||
#define VIRTIO_ID_IOMMU 23 /* virtio IOMMU */
|
||||
#define VIRTIO_ID_FS 26 /* virtio filesystem */
|
||||
#define VIRTIO_ID_PMEM 27 /* virtio pmem */
|
||||
|
||||
#endif /* _LINUX_VIRTIO_IDS_H */
|
||||
|
|
165
include/standard-headers/linux/virtio_iommu.h
Normal file
165
include/standard-headers/linux/virtio_iommu.h
Normal file
|
@ -0,0 +1,165 @@
|
|||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
/*
|
||||
* Virtio-iommu definition v0.12
|
||||
*
|
||||
* Copyright (C) 2019 Arm Ltd.
|
||||
*/
|
||||
#ifndef _LINUX_VIRTIO_IOMMU_H
|
||||
#define _LINUX_VIRTIO_IOMMU_H
|
||||
|
||||
#include "standard-headers/linux/types.h"
|
||||
|
||||
/* Feature bits */
|
||||
#define VIRTIO_IOMMU_F_INPUT_RANGE 0
|
||||
#define VIRTIO_IOMMU_F_DOMAIN_RANGE 1
|
||||
#define VIRTIO_IOMMU_F_MAP_UNMAP 2
|
||||
#define VIRTIO_IOMMU_F_BYPASS 3
|
||||
#define VIRTIO_IOMMU_F_PROBE 4
|
||||
#define VIRTIO_IOMMU_F_MMIO 5
|
||||
|
||||
struct virtio_iommu_range_64 {
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
};
|
||||
|
||||
struct virtio_iommu_range_32 {
|
||||
uint32_t start;
|
||||
uint32_t end;
|
||||
};
|
||||
|
||||
struct virtio_iommu_config {
|
||||
/* Supported page sizes */
|
||||
uint64_t page_size_mask;
|
||||
/* Supported IOVA range */
|
||||
struct virtio_iommu_range_64 input_range;
|
||||
/* Max domain ID size */
|
||||
struct virtio_iommu_range_32 domain_range;
|
||||
/* Probe buffer size */
|
||||
uint32_t probe_size;
|
||||
};
|
||||
|
||||
/* Request types */
|
||||
#define VIRTIO_IOMMU_T_ATTACH 0x01
|
||||
#define VIRTIO_IOMMU_T_DETACH 0x02
|
||||
#define VIRTIO_IOMMU_T_MAP 0x03
|
||||
#define VIRTIO_IOMMU_T_UNMAP 0x04
|
||||
#define VIRTIO_IOMMU_T_PROBE 0x05
|
||||
|
||||
/* Status types */
|
||||
#define VIRTIO_IOMMU_S_OK 0x00
|
||||
#define VIRTIO_IOMMU_S_IOERR 0x01
|
||||
#define VIRTIO_IOMMU_S_UNSUPP 0x02
|
||||
#define VIRTIO_IOMMU_S_DEVERR 0x03
|
||||
#define VIRTIO_IOMMU_S_INVAL 0x04
|
||||
#define VIRTIO_IOMMU_S_RANGE 0x05
|
||||
#define VIRTIO_IOMMU_S_NOENT 0x06
|
||||
#define VIRTIO_IOMMU_S_FAULT 0x07
|
||||
#define VIRTIO_IOMMU_S_NOMEM 0x08
|
||||
|
||||
struct virtio_iommu_req_head {
|
||||
uint8_t type;
|
||||
uint8_t reserved[3];
|
||||
};
|
||||
|
||||
struct virtio_iommu_req_tail {
|
||||
uint8_t status;
|
||||
uint8_t reserved[3];
|
||||
};
|
||||
|
||||
struct virtio_iommu_req_attach {
|
||||
struct virtio_iommu_req_head head;
|
||||
uint32_t domain;
|
||||
uint32_t endpoint;
|
||||
uint8_t reserved[8];
|
||||
struct virtio_iommu_req_tail tail;
|
||||
};
|
||||
|
||||
struct virtio_iommu_req_detach {
|
||||
struct virtio_iommu_req_head head;
|
||||
uint32_t domain;
|
||||
uint32_t endpoint;
|
||||
uint8_t reserved[8];
|
||||
struct virtio_iommu_req_tail tail;
|
||||
};
|
||||
|
||||
#define VIRTIO_IOMMU_MAP_F_READ (1 << 0)
|
||||
#define VIRTIO_IOMMU_MAP_F_WRITE (1 << 1)
|
||||
#define VIRTIO_IOMMU_MAP_F_MMIO (1 << 2)
|
||||
|
||||
#define VIRTIO_IOMMU_MAP_F_MASK (VIRTIO_IOMMU_MAP_F_READ | \
|
||||
VIRTIO_IOMMU_MAP_F_WRITE | \
|
||||
VIRTIO_IOMMU_MAP_F_MMIO)
|
||||
|
||||
struct virtio_iommu_req_map {
|
||||
struct virtio_iommu_req_head head;
|
||||
uint32_t domain;
|
||||
uint64_t virt_start;
|
||||
uint64_t virt_end;
|
||||
uint64_t phys_start;
|
||||
uint32_t flags;
|
||||
struct virtio_iommu_req_tail tail;
|
||||
};
|
||||
|
||||
struct virtio_iommu_req_unmap {
|
||||
struct virtio_iommu_req_head head;
|
||||
uint32_t domain;
|
||||
uint64_t virt_start;
|
||||
uint64_t virt_end;
|
||||
uint8_t reserved[4];
|
||||
struct virtio_iommu_req_tail tail;
|
||||
};
|
||||
|
||||
#define VIRTIO_IOMMU_PROBE_T_NONE 0
|
||||
#define VIRTIO_IOMMU_PROBE_T_RESV_MEM 1
|
||||
|
||||
#define VIRTIO_IOMMU_PROBE_T_MASK 0xfff
|
||||
|
||||
struct virtio_iommu_probe_property {
|
||||
uint16_t type;
|
||||
uint16_t length;
|
||||
};
|
||||
|
||||
#define VIRTIO_IOMMU_RESV_MEM_T_RESERVED 0
|
||||
#define VIRTIO_IOMMU_RESV_MEM_T_MSI 1
|
||||
|
||||
struct virtio_iommu_probe_resv_mem {
|
||||
struct virtio_iommu_probe_property head;
|
||||
uint8_t subtype;
|
||||
uint8_t reserved[3];
|
||||
uint64_t start;
|
||||
uint64_t end;
|
||||
};
|
||||
|
||||
struct virtio_iommu_req_probe {
|
||||
struct virtio_iommu_req_head head;
|
||||
uint32_t endpoint;
|
||||
uint8_t reserved[64];
|
||||
|
||||
uint8_t properties[];
|
||||
|
||||
/*
|
||||
* Tail follows the variable-length properties array. No padding,
|
||||
* property lengths are all aligned on 8 bytes.
|
||||
*/
|
||||
};
|
||||
|
||||
/* Fault types */
|
||||
#define VIRTIO_IOMMU_FAULT_R_UNKNOWN 0
|
||||
#define VIRTIO_IOMMU_FAULT_R_DOMAIN 1
|
||||
#define VIRTIO_IOMMU_FAULT_R_MAPPING 2
|
||||
|
||||
#define VIRTIO_IOMMU_FAULT_F_READ (1 << 0)
|
||||
#define VIRTIO_IOMMU_FAULT_F_WRITE (1 << 1)
|
||||
#define VIRTIO_IOMMU_FAULT_F_EXEC (1 << 2)
|
||||
#define VIRTIO_IOMMU_FAULT_F_ADDRESS (1 << 8)
|
||||
|
||||
struct virtio_iommu_fault {
|
||||
uint8_t reason;
|
||||
uint8_t reserved[3];
|
||||
uint32_t flags;
|
||||
uint32_t endpoint;
|
||||
uint8_t reserved2[4];
|
||||
uint64_t address;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
|
||||
/* SPDX-License-Identifier: (GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause */
|
||||
/*
|
||||
* Definitions for virtio-pmem devices.
|
||||
*
|
||||
|
@ -7,8 +7,8 @@
|
|||
* Author(s): Pankaj Gupta <pagupta@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef _UAPI_LINUX_VIRTIO_PMEM_H
|
||||
#define _UAPI_LINUX_VIRTIO_PMEM_H
|
||||
#ifndef _LINUX_VIRTIO_PMEM_H
|
||||
#define _LINUX_VIRTIO_PMEM_H
|
||||
|
||||
#include "standard-headers/linux/types.h"
|
||||
#include "standard-headers/linux/virtio_ids.h"
|
||||
|
|
|
@ -214,6 +214,18 @@ struct kvm_vcpu_events {
|
|||
#define KVM_REG_ARM_FW_REG(r) (KVM_REG_ARM | KVM_REG_SIZE_U64 | \
|
||||
KVM_REG_ARM_FW | ((r) & 0xffff))
|
||||
#define KVM_REG_ARM_PSCI_VERSION KVM_REG_ARM_FW_REG(0)
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1 KVM_REG_ARM_FW_REG(1)
|
||||
/* Higher values mean better protection. */
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL 0
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL 1
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED 2
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2 KVM_REG_ARM_FW_REG(2)
|
||||
/* Higher values mean better protection. */
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL 0
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN 1
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL 2
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED 3
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED (1U << 4)
|
||||
|
||||
/* Device Control API: ARM VGIC */
|
||||
#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
|
||||
|
@ -254,8 +266,10 @@ struct kvm_vcpu_events {
|
|||
#define KVM_DEV_ARM_ITS_CTRL_RESET 4
|
||||
|
||||
/* KVM_IRQ_LINE irq field index values */
|
||||
#define KVM_ARM_IRQ_VCPU2_SHIFT 28
|
||||
#define KVM_ARM_IRQ_VCPU2_MASK 0xf
|
||||
#define KVM_ARM_IRQ_TYPE_SHIFT 24
|
||||
#define KVM_ARM_IRQ_TYPE_MASK 0xff
|
||||
#define KVM_ARM_IRQ_TYPE_MASK 0xf
|
||||
#define KVM_ARM_IRQ_VCPU_SHIFT 16
|
||||
#define KVM_ARM_IRQ_VCPU_MASK 0xff
|
||||
#define KVM_ARM_IRQ_NUM_SHIFT 0
|
||||
|
|
|
@ -388,5 +388,7 @@
|
|||
#define __NR_fsconfig (__NR_SYSCALL_BASE + 431)
|
||||
#define __NR_fsmount (__NR_SYSCALL_BASE + 432)
|
||||
#define __NR_fspick (__NR_SYSCALL_BASE + 433)
|
||||
#define __NR_pidfd_open (__NR_SYSCALL_BASE + 434)
|
||||
#define __NR_clone3 (__NR_SYSCALL_BASE + 435)
|
||||
|
||||
#endif /* _ASM_ARM_UNISTD_COMMON_H */
|
||||
|
|
|
@ -229,6 +229,16 @@ struct kvm_vcpu_events {
|
|||
#define KVM_REG_ARM_FW_REG(r) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
|
||||
KVM_REG_ARM_FW | ((r) & 0xffff))
|
||||
#define KVM_REG_ARM_PSCI_VERSION KVM_REG_ARM_FW_REG(0)
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1 KVM_REG_ARM_FW_REG(1)
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_AVAIL 0
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_AVAIL 1
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1_NOT_REQUIRED 2
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2 KVM_REG_ARM_FW_REG(2)
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL 0
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_UNKNOWN 1
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_AVAIL 2
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED 3
|
||||
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED (1U << 4)
|
||||
|
||||
/* SVE registers */
|
||||
#define KVM_REG_ARM64_SVE (0x15 << KVM_REG_ARM_COPROC_SHIFT)
|
||||
|
@ -260,6 +270,13 @@ struct kvm_vcpu_events {
|
|||
KVM_REG_SIZE_U256 | \
|
||||
((i) & (KVM_ARM64_SVE_MAX_SLICES - 1)))
|
||||
|
||||
/*
|
||||
* Register values for KVM_REG_ARM64_SVE_ZREG(), KVM_REG_ARM64_SVE_PREG() and
|
||||
* KVM_REG_ARM64_SVE_FFR() are represented in memory in an endianness-
|
||||
* invariant layout which differs from the layout used for the FPSIMD
|
||||
* V-registers on big-endian systems: see sigcontext.h for more explanation.
|
||||
*/
|
||||
|
||||
#define KVM_ARM64_SVE_VQ_MIN __SVE_VQ_MIN
|
||||
#define KVM_ARM64_SVE_VQ_MAX __SVE_VQ_MAX
|
||||
|
||||
|
@ -308,8 +325,10 @@ struct kvm_vcpu_events {
|
|||
#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
|
||||
|
||||
/* KVM_IRQ_LINE irq field index values */
|
||||
#define KVM_ARM_IRQ_VCPU2_SHIFT 28
|
||||
#define KVM_ARM_IRQ_VCPU2_MASK 0xf
|
||||
#define KVM_ARM_IRQ_TYPE_SHIFT 24
|
||||
#define KVM_ARM_IRQ_TYPE_MASK 0xff
|
||||
#define KVM_ARM_IRQ_TYPE_MASK 0xf
|
||||
#define KVM_ARM_IRQ_VCPU_SHIFT 16
|
||||
#define KVM_ARM_IRQ_VCPU_MASK 0xff
|
||||
#define KVM_ARM_IRQ_NUM_SHIFT 0
|
||||
|
|
|
@ -19,15 +19,18 @@
|
|||
#define MAP_TYPE 0x0f /* Mask for type of mapping */
|
||||
#define MAP_FIXED 0x10 /* Interpret addr exactly */
|
||||
#define MAP_ANONYMOUS 0x20 /* don't use a file */
|
||||
#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
|
||||
# define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be uninitialized */
|
||||
#else
|
||||
# define MAP_UNINITIALIZED 0x0 /* Don't support this flag */
|
||||
#endif
|
||||
|
||||
/* 0x0100 - 0x80000 flags are defined in asm-generic/mman.h */
|
||||
/* 0x0100 - 0x4000 flags are defined in asm-generic/mman.h */
|
||||
#define MAP_POPULATE 0x008000 /* populate (prefault) pagetables */
|
||||
#define MAP_NONBLOCK 0x010000 /* do not block on IO */
|
||||
#define MAP_STACK 0x020000 /* give out an address that is best suited for process/thread stacks */
|
||||
#define MAP_HUGETLB 0x040000 /* create a huge page mapping */
|
||||
#define MAP_SYNC 0x080000 /* perform synchronous page faults for the mapping */
|
||||
#define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */
|
||||
|
||||
#define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be
|
||||
* uninitialized */
|
||||
|
||||
/*
|
||||
* Flags for mlock
|
||||
*/
|
||||
|
@ -64,6 +67,9 @@
|
|||
#define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */
|
||||
#define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */
|
||||
|
||||
#define MADV_COLD 20 /* deactivate these pages */
|
||||
#define MADV_PAGEOUT 21 /* reclaim these pages */
|
||||
|
||||
/* compatibility flags */
|
||||
#define MAP_FILE 0
|
||||
|
||||
|
|
|
@ -9,13 +9,11 @@
|
|||
#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
|
||||
#define MAP_LOCKED 0x2000 /* pages are locked */
|
||||
#define MAP_NORESERVE 0x4000 /* don't check for reservations */
|
||||
#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
|
||||
#define MAP_NONBLOCK 0x10000 /* do not block on IO */
|
||||
#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
|
||||
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
|
||||
#define MAP_SYNC 0x80000 /* perform synchronous page faults for the mapping */
|
||||
|
||||
/* Bits [26:31] are reserved, see mman-common.h for MAP_HUGETLB usage */
|
||||
/*
|
||||
* Bits [26:31] are reserved, see asm-generic/hugetlb_encode.h
|
||||
* for MAP_HUGETLB usage
|
||||
*/
|
||||
|
||||
#define MCL_CURRENT 1 /* lock all current mappings */
|
||||
#define MCL_FUTURE 2 /* lock all future mappings */
|
||||
|
|
|
@ -569,7 +569,7 @@ __SYSCALL(__NR_semget, sys_semget)
|
|||
__SC_COMP(__NR_semctl, sys_semctl, compat_sys_semctl)
|
||||
#if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32
|
||||
#define __NR_semtimedop 192
|
||||
__SC_COMP(__NR_semtimedop, sys_semtimedop, sys_semtimedop_time32)
|
||||
__SC_3264(__NR_semtimedop, sys_semtimedop_time32, sys_semtimedop)
|
||||
#endif
|
||||
#define __NR_semop 193
|
||||
__SYSCALL(__NR_semop, sys_semop)
|
||||
|
@ -844,9 +844,15 @@ __SYSCALL(__NR_fsconfig, sys_fsconfig)
|
|||
__SYSCALL(__NR_fsmount, sys_fsmount)
|
||||
#define __NR_fspick 433
|
||||
__SYSCALL(__NR_fspick, sys_fspick)
|
||||
#define __NR_pidfd_open 434
|
||||
__SYSCALL(__NR_pidfd_open, sys_pidfd_open)
|
||||
#ifdef __ARCH_WANT_SYS_CLONE3
|
||||
#define __NR_clone3 435
|
||||
__SYSCALL(__NR_clone3, sys_clone3)
|
||||
#endif
|
||||
|
||||
#undef __NR_syscalls
|
||||
#define __NR_syscalls 434
|
||||
#define __NR_syscalls 436
|
||||
|
||||
/*
|
||||
* 32 bit systems traditionally used different
|
||||
|
|
|
@ -95,6 +95,9 @@
|
|||
#define MADV_WIPEONFORK 18 /* Zero memory on fork, child only */
|
||||
#define MADV_KEEPONFORK 19 /* Undo MADV_WIPEONFORK */
|
||||
|
||||
#define MADV_COLD 20 /* deactivate these pages */
|
||||
#define MADV_PAGEOUT 21 /* reclaim these pages */
|
||||
|
||||
/* compatibility flags */
|
||||
#define MAP_FILE 0
|
||||
|
||||
|
|
|
@ -363,6 +363,7 @@
|
|||
#define __NR_fsconfig (__NR_Linux + 431)
|
||||
#define __NR_fsmount (__NR_Linux + 432)
|
||||
#define __NR_fspick (__NR_Linux + 433)
|
||||
#define __NR_pidfd_open (__NR_Linux + 434)
|
||||
|
||||
|
||||
#endif /* _ASM_MIPS_UNISTD_N32_H */
|
||||
|
|
|
@ -339,6 +339,7 @@
|
|||
#define __NR_fsconfig (__NR_Linux + 431)
|
||||
#define __NR_fsmount (__NR_Linux + 432)
|
||||
#define __NR_fspick (__NR_Linux + 433)
|
||||
#define __NR_pidfd_open (__NR_Linux + 434)
|
||||
|
||||
|
||||
#endif /* _ASM_MIPS_UNISTD_N64_H */
|
||||
|
|
|
@ -409,6 +409,7 @@
|
|||
#define __NR_fsconfig (__NR_Linux + 431)
|
||||
#define __NR_fsmount (__NR_Linux + 432)
|
||||
#define __NR_fspick (__NR_Linux + 433)
|
||||
#define __NR_pidfd_open (__NR_Linux + 434)
|
||||
|
||||
|
||||
#endif /* _ASM_MIPS_UNISTD_O32_H */
|
||||
|
|
|
@ -21,15 +21,11 @@
|
|||
#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
|
||||
#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
|
||||
|
||||
|
||||
#define MCL_CURRENT 0x2000 /* lock all currently mapped pages */
|
||||
#define MCL_FUTURE 0x4000 /* lock all additions to address space */
|
||||
#define MCL_ONFAULT 0x8000 /* lock all pages that are faulted in */
|
||||
|
||||
#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
|
||||
#define MAP_NONBLOCK 0x10000 /* do not block on IO */
|
||||
#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
|
||||
#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
|
||||
|
||||
/* Override any generic PKEY permission defines */
|
||||
#define PKEY_DISABLE_EXECUTE 0x4
|
||||
#undef PKEY_ACCESS_MASK
|
||||
|
|
|
@ -416,6 +416,8 @@
|
|||
#define __NR_fsconfig 431
|
||||
#define __NR_fsmount 432
|
||||
#define __NR_fspick 433
|
||||
#define __NR_pidfd_open 434
|
||||
#define __NR_clone3 435
|
||||
|
||||
|
||||
#endif /* _ASM_POWERPC_UNISTD_32_H */
|
||||
|
|
|
@ -388,6 +388,8 @@
|
|||
#define __NR_fsconfig 431
|
||||
#define __NR_fsmount 432
|
||||
#define __NR_fspick 433
|
||||
#define __NR_pidfd_open 434
|
||||
#define __NR_clone3 435
|
||||
|
||||
|
||||
#endif /* _ASM_POWERPC_UNISTD_64_H */
|
||||
|
|
|
@ -231,6 +231,12 @@ struct kvm_guest_debug_arch {
|
|||
#define KVM_SYNC_GSCB (1UL << 9)
|
||||
#define KVM_SYNC_BPBC (1UL << 10)
|
||||
#define KVM_SYNC_ETOKEN (1UL << 11)
|
||||
|
||||
#define KVM_SYNC_S390_VALID_FIELDS \
|
||||
(KVM_SYNC_PREFIX | KVM_SYNC_GPRS | KVM_SYNC_ACRS | KVM_SYNC_CRS | \
|
||||
KVM_SYNC_ARCH0 | KVM_SYNC_PFAULT | KVM_SYNC_VRS | KVM_SYNC_RICCB | \
|
||||
KVM_SYNC_FPRS | KVM_SYNC_GSCB | KVM_SYNC_BPBC | KVM_SYNC_ETOKEN)
|
||||
|
||||
/* length and alignment of the sdnx as a power of two */
|
||||
#define SDNXC 8
|
||||
#define SDNXL (1UL << SDNXC)
|
||||
|
|
|
@ -406,5 +406,7 @@
|
|||
#define __NR_fsconfig 431
|
||||
#define __NR_fsmount 432
|
||||
#define __NR_fspick 433
|
||||
#define __NR_pidfd_open 434
|
||||
#define __NR_clone3 435
|
||||
|
||||
#endif /* _ASM_S390_UNISTD_32_H */
|
||||
|
|
|
@ -354,5 +354,7 @@
|
|||
#define __NR_fsconfig 431
|
||||
#define __NR_fsmount 432
|
||||
#define __NR_fspick 433
|
||||
#define __NR_pidfd_open 434
|
||||
#define __NR_clone3 435
|
||||
|
||||
#endif /* _ASM_S390_UNISTD_64_H */
|
||||
|
|
|
@ -378,23 +378,24 @@ struct kvm_sync_regs {
|
|||
struct kvm_vcpu_events events;
|
||||
};
|
||||
|
||||
#define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0)
|
||||
#define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1)
|
||||
#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2)
|
||||
#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3)
|
||||
#define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0)
|
||||
#define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1)
|
||||
#define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2)
|
||||
#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3)
|
||||
#define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4)
|
||||
|
||||
#define KVM_STATE_NESTED_FORMAT_VMX 0
|
||||
#define KVM_STATE_NESTED_FORMAT_SVM 1
|
||||
#define KVM_STATE_NESTED_FORMAT_SVM 1 /* unused */
|
||||
|
||||
#define KVM_STATE_NESTED_GUEST_MODE 0x00000001
|
||||
#define KVM_STATE_NESTED_RUN_PENDING 0x00000002
|
||||
#define KVM_STATE_NESTED_EVMCS 0x00000004
|
||||
|
||||
#define KVM_STATE_NESTED_VMX_VMCS_SIZE 0x1000
|
||||
|
||||
#define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001
|
||||
#define KVM_STATE_NESTED_SMM_VMXON 0x00000002
|
||||
|
||||
#define KVM_STATE_NESTED_VMX_VMCS_SIZE 0x1000
|
||||
|
||||
struct kvm_vmx_nested_state_data {
|
||||
__u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
|
||||
__u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE];
|
||||
|
@ -432,4 +433,17 @@ struct kvm_nested_state {
|
|||
} data;
|
||||
};
|
||||
|
||||
/* for KVM_CAP_PMU_EVENT_FILTER */
|
||||
struct kvm_pmu_event_filter {
|
||||
__u32 action;
|
||||
__u32 nevents;
|
||||
__u32 fixed_counter_bitmap;
|
||||
__u32 flags;
|
||||
__u32 pad[4];
|
||||
__u64 events[0];
|
||||
};
|
||||
|
||||
#define KVM_PMU_EVENT_ALLOW 0
|
||||
#define KVM_PMU_EVENT_DENY 1
|
||||
|
||||
#endif /* _ASM_X86_KVM_H */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#define _ASM_X86_UNISTD_H
|
||||
|
||||
/* x32 syscall flag bit */
|
||||
#define __X32_SYSCALL_BIT 0x40000000
|
||||
#define __X32_SYSCALL_BIT 0x40000000UL
|
||||
|
||||
# ifdef __i386__
|
||||
# include <asm/unistd_32.h>
|
||||
|
|
|
@ -424,5 +424,7 @@
|
|||
#define __NR_fsconfig 431
|
||||
#define __NR_fsmount 432
|
||||
#define __NR_fspick 433
|
||||
#define __NR_pidfd_open 434
|
||||
#define __NR_clone3 435
|
||||
|
||||
#endif /* _ASM_X86_UNISTD_32_H */
|
||||
|
|
|
@ -346,5 +346,7 @@
|
|||
#define __NR_fsconfig 431
|
||||
#define __NR_fsmount 432
|
||||
#define __NR_fspick 433
|
||||
#define __NR_pidfd_open 434
|
||||
#define __NR_clone3 435
|
||||
|
||||
#endif /* _ASM_X86_UNISTD_64_H */
|
||||
|
|
|
@ -299,6 +299,8 @@
|
|||
#define __NR_fsconfig (__X32_SYSCALL_BIT + 431)
|
||||
#define __NR_fsmount (__X32_SYSCALL_BIT + 432)
|
||||
#define __NR_fspick (__X32_SYSCALL_BIT + 433)
|
||||
#define __NR_pidfd_open (__X32_SYSCALL_BIT + 434)
|
||||
#define __NR_clone3 (__X32_SYSCALL_BIT + 435)
|
||||
#define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512)
|
||||
#define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513)
|
||||
#define __NR_ioctl (__X32_SYSCALL_BIT + 514)
|
||||
|
|
|
@ -116,7 +116,7 @@ struct kvm_irq_level {
|
|||
* ACPI gsi notion of irq.
|
||||
* For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47..
|
||||
* For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23..
|
||||
* For ARM: See Documentation/virtual/kvm/api.txt
|
||||
* For ARM: See Documentation/virt/kvm/api.txt
|
||||
*/
|
||||
union {
|
||||
__u32 irq;
|
||||
|
@ -243,6 +243,8 @@ struct kvm_hyperv_exit {
|
|||
#define KVM_INTERNAL_ERROR_SIMUL_EX 2
|
||||
/* Encounter unexpected vm-exit due to delivery event. */
|
||||
#define KVM_INTERNAL_ERROR_DELIVERY_EV 3
|
||||
/* Encounter unexpected vm-exit reason */
|
||||
#define KVM_INTERNAL_ERROR_UNEXPECTED_EXIT_REASON 4
|
||||
|
||||
/* for KVM_RUN, returned by mmap(vcpu_fd, offset=0) */
|
||||
struct kvm_run {
|
||||
|
@ -995,6 +997,9 @@ struct kvm_ppc_resize_hpt {
|
|||
#define KVM_CAP_ARM_SVE 170
|
||||
#define KVM_CAP_ARM_PTRAUTH_ADDRESS 171
|
||||
#define KVM_CAP_ARM_PTRAUTH_GENERIC 172
|
||||
#define KVM_CAP_PMU_EVENT_FILTER 173
|
||||
#define KVM_CAP_ARM_IRQ_LINE_LAYOUT_2 174
|
||||
#define KVM_CAP_HYPERV_DIRECT_TLBFLUSH 175
|
||||
|
||||
#ifdef KVM_CAP_IRQ_ROUTING
|
||||
|
||||
|
@ -1085,7 +1090,7 @@ struct kvm_xen_hvm_config {
|
|||
*
|
||||
* KVM_IRQFD_FLAG_RESAMPLE indicates resamplefd is valid and specifies
|
||||
* the irqfd to operate in resampling mode for level triggered interrupt
|
||||
* emulation. See Documentation/virtual/kvm/api.txt.
|
||||
* emulation. See Documentation/virt/kvm/api.txt.
|
||||
*/
|
||||
#define KVM_IRQFD_FLAG_RESAMPLE (1 << 1)
|
||||
|
||||
|
@ -1141,6 +1146,7 @@ struct kvm_dirty_tlb {
|
|||
#define KVM_REG_S390 0x5000000000000000ULL
|
||||
#define KVM_REG_ARM64 0x6000000000000000ULL
|
||||
#define KVM_REG_MIPS 0x7000000000000000ULL
|
||||
#define KVM_REG_RISCV 0x8000000000000000ULL
|
||||
|
||||
#define KVM_REG_SIZE_SHIFT 52
|
||||
#define KVM_REG_SIZE_MASK 0x00f0000000000000ULL
|
||||
|
@ -1329,6 +1335,8 @@ struct kvm_s390_ucas_mapping {
|
|||
#define KVM_PPC_GET_RMMU_INFO _IOW(KVMIO, 0xb0, struct kvm_ppc_rmmu_info)
|
||||
/* Available with KVM_CAP_PPC_GET_CPU_CHAR */
|
||||
#define KVM_PPC_GET_CPU_CHAR _IOR(KVMIO, 0xb1, struct kvm_ppc_cpu_char)
|
||||
/* Available with KVM_CAP_PMU_EVENT_FILTER */
|
||||
#define KVM_SET_PMU_EVENT_FILTER _IOW(KVMIO, 0xb2, struct kvm_pmu_event_filter)
|
||||
|
||||
/* ioctl for vm fd */
|
||||
#define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||
/*
|
||||
* Userspace interface for AMD Secure Encrypted Virtualization (SEV)
|
||||
* platform management commands.
|
||||
|
@ -7,10 +8,6 @@
|
|||
* Author: Brijesh Singh <brijesh.singh@amd.com>
|
||||
*
|
||||
* SEV API specification is available at: https://developer.amd.com/sev/
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef __PSP_SEV_USER_H__
|
||||
|
|
|
@ -295,15 +295,38 @@ struct vfio_region_info_cap_type {
|
|||
__u32 subtype; /* type specific */
|
||||
};
|
||||
|
||||
/*
|
||||
* List of region types, global per bus driver.
|
||||
* If you introduce a new type, please add it here.
|
||||
*/
|
||||
|
||||
/* PCI region type containing a PCI vendor part */
|
||||
#define VFIO_REGION_TYPE_PCI_VENDOR_TYPE (1 << 31)
|
||||
#define VFIO_REGION_TYPE_PCI_VENDOR_MASK (0xffff)
|
||||
#define VFIO_REGION_TYPE_GFX (1)
|
||||
#define VFIO_REGION_TYPE_CCW (2)
|
||||
|
||||
/* 8086 Vendor sub-types */
|
||||
/* sub-types for VFIO_REGION_TYPE_PCI_* */
|
||||
|
||||
/* 8086 vendor PCI sub-types */
|
||||
#define VFIO_REGION_SUBTYPE_INTEL_IGD_OPREGION (1)
|
||||
#define VFIO_REGION_SUBTYPE_INTEL_IGD_HOST_CFG (2)
|
||||
#define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG (3)
|
||||
|
||||
#define VFIO_REGION_TYPE_GFX (1)
|
||||
/* 10de vendor PCI sub-types */
|
||||
/*
|
||||
* NVIDIA GPU NVlink2 RAM is coherent RAM mapped onto the host address space.
|
||||
*/
|
||||
#define VFIO_REGION_SUBTYPE_NVIDIA_NVLINK2_RAM (1)
|
||||
|
||||
/* 1014 vendor PCI sub-types */
|
||||
/*
|
||||
* IBM NPU NVlink2 ATSD (Address Translation Shootdown) register of NPU
|
||||
* to do TLB invalidation on a GPU.
|
||||
*/
|
||||
#define VFIO_REGION_SUBTYPE_IBM_NVLINK2_ATSD (1)
|
||||
|
||||
/* sub-types for VFIO_REGION_TYPE_GFX */
|
||||
#define VFIO_REGION_SUBTYPE_GFX_EDID (1)
|
||||
|
||||
/**
|
||||
|
@ -353,25 +376,9 @@ struct vfio_region_gfx_edid {
|
|||
#define VFIO_DEVICE_GFX_LINK_STATE_DOWN 2
|
||||
};
|
||||
|
||||
#define VFIO_REGION_TYPE_CCW (2)
|
||||
/* ccw sub-types */
|
||||
/* sub-types for VFIO_REGION_TYPE_CCW */
|
||||
#define VFIO_REGION_SUBTYPE_CCW_ASYNC_CMD (1)
|
||||
|
||||
/*
|
||||
* 10de vendor sub-type
|
||||
*
|
||||
* NVIDIA GPU NVlink2 RAM is coherent RAM mapped onto the host address space.
|
||||
*/
|
||||
#define VFIO_REGION_SUBTYPE_NVIDIA_NVLINK2_RAM (1)
|
||||
|
||||
/*
|
||||
* 1014 vendor sub-type
|
||||
*
|
||||
* IBM NPU NVlink2 ATSD (Address Translation Shootdown) register of NPU
|
||||
* to do TLB invalidation on a GPU.
|
||||
*/
|
||||
#define VFIO_REGION_SUBTYPE_IBM_NVLINK2_ATSD (1)
|
||||
|
||||
/*
|
||||
* The MSIX mappable capability informs that MSIX data of a BAR can be mmapped
|
||||
* which allows direct access to non-MSIX registers which happened to be within
|
||||
|
@ -714,7 +721,31 @@ struct vfio_iommu_type1_info {
|
|||
__u32 argsz;
|
||||
__u32 flags;
|
||||
#define VFIO_IOMMU_INFO_PGSIZES (1 << 0) /* supported page sizes info */
|
||||
__u64 iova_pgsizes; /* Bitmap of supported page sizes */
|
||||
#define VFIO_IOMMU_INFO_CAPS (1 << 1) /* Info supports caps */
|
||||
__u64 iova_pgsizes; /* Bitmap of supported page sizes */
|
||||
__u32 cap_offset; /* Offset within info struct of first cap */
|
||||
};
|
||||
|
||||
/*
|
||||
* The IOVA capability allows to report the valid IOVA range(s)
|
||||
* excluding any non-relaxable reserved regions exposed by
|
||||
* devices attached to the container. Any DMA map attempt
|
||||
* outside the valid iova range will return error.
|
||||
*
|
||||
* The structures below define version 1 of this capability.
|
||||
*/
|
||||
#define VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE 1
|
||||
|
||||
struct vfio_iova_range {
|
||||
__u64 start;
|
||||
__u64 end;
|
||||
};
|
||||
|
||||
struct vfio_iommu_type1_info_cap_iova_range {
|
||||
struct vfio_info_cap_header header;
|
||||
__u32 nr_iovas;
|
||||
__u32 reserved;
|
||||
struct vfio_iova_range iova_ranges[];
|
||||
};
|
||||
|
||||
#define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue