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:
Peter Maydell 2019-10-15 18:15:59 +01:00
commit 69b81893bc
105 changed files with 3934 additions and 650 deletions

View File

@ -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

View File

@ -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
View 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)

View File

@ -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)

View File

@ -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)

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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;

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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);

View File

@ -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"

View File

@ -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);
}

View File

@ -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)

View File

@ -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[] = {

View File

@ -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
View 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)

View File

@ -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 */

View File

@ -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);
}
}

View File

@ -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,

View File

@ -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,
};

View File

@ -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;
}

View File

@ -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)

View File

@ -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 |

View File

@ -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 = {

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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 */

View File

@ -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)

View File

@ -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)

View File

@ -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);
}

View File

@ -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);

View File

@ -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);
}

View File

@ -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",

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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 = {

View File

@ -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)

View File

@ -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,
};

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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);

View 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 */

View File

@ -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 {

View File

@ -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 */

View File

@ -46,7 +46,6 @@
#define R_TIM1_MAX 6
struct Msf2Timer {
QEMUBH *bh;
ptimer_state *ptimer;
uint32_t regs[R_TIM1_MAX];

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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 */

View 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 */

View File

@ -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 */

View 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

View File

@ -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"

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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)

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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>

View File

@ -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 */

View File

@ -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 */

View File

@ -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)

View File

@ -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)

View File

@ -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__

View File

@ -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