Aspeed patches :

* I2C QOMify (Cedric)
 * SMC model cleanup and QOMify (Cedric)
 * ADC model (Peter and Andrew)
 * GPIO fixes (Peter)
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmFlOvYACgkQUaNDx8/7
 7KGimQ/+LG8B04Aveo74ezIX0GCNQIi6ZVRAzPBOsHZ1FSW3rXfOxr1k/uUWDWiC
 t05r9e63f4IPVtoP14H8zFnQngddG2Q3AByOilJLRYYct3N6G+ewUqBmR1LN+iBZ
 1F/koyNvBNfCBQHCmPHsJF6UGgs48NbXPWoQX2Dsudkkxk3KS+RTUrtIk4fD9tB9
 a5lDxSjJ756pkQkvS7tCLjyGB4rOicfEE0gDh4Uyr3+t9VRXPVCSG7NX1jvytZ2t
 1udj7MmnNEjY0CtUFjtfjog5f3gcXU40lGmbvNxEB8dPykJnnPqbdSWtStRryN5L
 FVvOeP4rKb0jF0TmNsBWTtSZvNuNBzQkwL/tYgzJ+bKNVoYQUDHzhWsC99GqH9Vi
 +z3s5TlEqiTN1krw8+0vF/4GeTse0lsYuGIvD3jqdrERCtpPvmSynMWXtIGi/QOr
 ILVXaSbJ4A6ZkAXQjKNVOGqqEeQqr96synSeyiNQs9su9X/Sl5P71r9mFRhVV9T7
 4EgvzGQCMIH+aL/nMnb2IhQNd/3sq51wc+TOnmb+by22s85LWvaSuBQVI2kvDn4v
 Bckl11qP6AZFu2xvq+mGnPI3cXRm57N5S499mwF+wygLpWOQI2CjoUunC+0GWQ7O
 ISMvukTskpwOkDNbfTB+e0cT80w5REdIcLL5oLmxcA+s35zthb8=
 =ydTX
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/clg/tags/pull-aspeed-20211012' into staging

Aspeed patches :

* I2C QOMify (Cedric)
* SMC model cleanup and QOMify (Cedric)
* ADC model (Peter and Andrew)
* GPIO fixes (Peter)

# gpg: Signature made Tue 12 Oct 2021 12:36:22 AM PDT
# gpg:                using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1
# gpg: Good signature from "Cédric Le Goater <clg@kaod.org>" [marginal]
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: A0F6 6548 F048 95EB FE6B  0B60 51A3 43C7 CFFB ECA1

* remotes/clg/tags/pull-aspeed-20211012:
  aspeed/smc: Dump address offset in trace events
  aspeed/wdt: Add trace events
  hw/arm: Integrate ADC model into Aspeed SoC
  hw/adc: Add basic Aspeed ADC model
  hw: aspeed_gpio: Fix GPIO array indexing
  hw: aspeed_gpio: Fix pin I/O type declarations
  aspeed/i2c: QOMify AspeedI2CBus
  aspeed/smc: Remove unused attribute 'irqline'
  aspeed/smc: Introduce a new addr_width() class handler
  aspeed/smc: Add default reset values
  aspeed/smc: QOMify AspeedSMCFlash
  aspeed/smc: Rename AspeedSMCFlash 'id' to 'cs'
  aspeed/smc: Remove the 'size' attribute from AspeedSMCFlash
  aspeed/smc: Remove the 'flash' attribute from AspeedSMCFlash
  aspeed/smc: Drop AspeedSMCController structure
  aspeed/smc: Stop using the model name for the memory regions
  aspeed/smc: Introduce aspeed_smc_error() helper
  aspeed/smc: Add watchdog Control/Status Registers

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2021-10-12 04:41:59 -07:00
commit 81d8537cb2
16 changed files with 1351 additions and 617 deletions

427
hw/adc/aspeed_adc.c Normal file
View File

@ -0,0 +1,427 @@
/*
* Aspeed ADC
*
* Copyright 2017-2021 IBM Corp.
*
* Andrew Jeffery <andrew@aj.id.au>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "qemu/osdep.h"
#include "qapi/error.h"
#include "qemu/log.h"
#include "hw/irq.h"
#include "hw/qdev-properties.h"
#include "migration/vmstate.h"
#include "hw/adc/aspeed_adc.h"
#include "trace.h"
#define ASPEED_ADC_MEMORY_REGION_SIZE 0x1000
#define ASPEED_ADC_ENGINE_MEMORY_REGION_SIZE 0x100
#define ASPEED_ADC_ENGINE_CH_EN_MASK 0xffff0000
#define ASPEED_ADC_ENGINE_CH_EN(x) ((BIT(x)) << 16)
#define ASPEED_ADC_ENGINE_INIT BIT(8)
#define ASPEED_ADC_ENGINE_AUTO_COMP BIT(5)
#define ASPEED_ADC_ENGINE_COMP BIT(4)
#define ASPEED_ADC_ENGINE_MODE_MASK 0x0000000e
#define ASPEED_ADC_ENGINE_MODE_OFF (0b000 << 1)
#define ASPEED_ADC_ENGINE_MODE_STANDBY (0b001 << 1)
#define ASPEED_ADC_ENGINE_MODE_NORMAL (0b111 << 1)
#define ASPEED_ADC_ENGINE_EN BIT(0)
#define ASPEED_ADC_HYST_EN BIT(31)
#define ASPEED_ADC_L_MASK ((1 << 10) - 1)
#define ASPEED_ADC_L(x) ((x) & ASPEED_ADC_L_MASK)
#define ASPEED_ADC_H(x) (((x) >> 16) & ASPEED_ADC_L_MASK)
#define ASPEED_ADC_LH_MASK (ASPEED_ADC_L_MASK << 16 | ASPEED_ADC_L_MASK)
#define LOWER_CHANNEL_MASK ((1 << 10) - 1)
#define LOWER_CHANNEL_DATA(x) ((x) & LOWER_CHANNEL_MASK)
#define UPPER_CHANNEL_DATA(x) (((x) >> 16) & LOWER_CHANNEL_MASK)
#define TO_REG(addr) (addr >> 2)
#define ENGINE_CONTROL TO_REG(0x00)
#define INTERRUPT_CONTROL TO_REG(0x04)
#define VGA_DETECT_CONTROL TO_REG(0x08)
#define CLOCK_CONTROL TO_REG(0x0C)
#define DATA_CHANNEL_1_AND_0 TO_REG(0x10)
#define DATA_CHANNEL_7_AND_6 TO_REG(0x1C)
#define DATA_CHANNEL_9_AND_8 TO_REG(0x20)
#define DATA_CHANNEL_15_AND_14 TO_REG(0x2C)
#define BOUNDS_CHANNEL_0 TO_REG(0x30)
#define BOUNDS_CHANNEL_7 TO_REG(0x4C)
#define BOUNDS_CHANNEL_8 TO_REG(0x50)
#define BOUNDS_CHANNEL_15 TO_REG(0x6C)
#define HYSTERESIS_CHANNEL_0 TO_REG(0x70)
#define HYSTERESIS_CHANNEL_7 TO_REG(0x8C)
#define HYSTERESIS_CHANNEL_8 TO_REG(0x90)
#define HYSTERESIS_CHANNEL_15 TO_REG(0xAC)
#define INTERRUPT_SOURCE TO_REG(0xC0)
#define COMPENSATING_AND_TRIMMING TO_REG(0xC4)
static inline uint32_t update_channels(uint32_t current)
{
return ((((current >> 16) & ASPEED_ADC_L_MASK) + 7) << 16) |
((current + 5) & ASPEED_ADC_L_MASK);
}
static bool breaks_threshold(AspeedADCEngineState *s, int reg)
{
assert(reg >= DATA_CHANNEL_1_AND_0 &&
reg < DATA_CHANNEL_1_AND_0 + s->nr_channels / 2);
int a_bounds_reg = BOUNDS_CHANNEL_0 + (reg - DATA_CHANNEL_1_AND_0) * 2;
int b_bounds_reg = a_bounds_reg + 1;
uint32_t a_and_b = s->regs[reg];
uint32_t a_bounds = s->regs[a_bounds_reg];
uint32_t b_bounds = s->regs[b_bounds_reg];
uint32_t a = ASPEED_ADC_L(a_and_b);
uint32_t b = ASPEED_ADC_H(a_and_b);
uint32_t a_lower = ASPEED_ADC_L(a_bounds);
uint32_t a_upper = ASPEED_ADC_H(a_bounds);
uint32_t b_lower = ASPEED_ADC_L(b_bounds);
uint32_t b_upper = ASPEED_ADC_H(b_bounds);
return (a < a_lower || a > a_upper) ||
(b < b_lower || b > b_upper);
}
static uint32_t read_channel_sample(AspeedADCEngineState *s, int reg)
{
assert(reg >= DATA_CHANNEL_1_AND_0 &&
reg < DATA_CHANNEL_1_AND_0 + s->nr_channels / 2);
/* Poor man's sampling */
uint32_t value = s->regs[reg];
s->regs[reg] = update_channels(s->regs[reg]);
if (breaks_threshold(s, reg)) {
s->regs[INTERRUPT_CONTROL] |= BIT(reg - DATA_CHANNEL_1_AND_0);
qemu_irq_raise(s->irq);
}
return value;
}
static uint64_t aspeed_adc_engine_read(void *opaque, hwaddr addr,
unsigned int size)
{
AspeedADCEngineState *s = ASPEED_ADC_ENGINE(opaque);
int reg = TO_REG(addr);
uint32_t value = 0;
switch (reg) {
case BOUNDS_CHANNEL_8 ... BOUNDS_CHANNEL_15:
if (s->nr_channels <= 8) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: engine[%u]: "
"bounds register %u invalid, only 0...7 valid\n",
__func__, s->engine_id, reg - BOUNDS_CHANNEL_0);
break;
}
/* fallthrough */
case HYSTERESIS_CHANNEL_8 ... HYSTERESIS_CHANNEL_15:
if (s->nr_channels <= 8) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: engine[%u]: "
"hysteresis register %u invalid, only 0...7 valid\n",
__func__, s->engine_id, reg - HYSTERESIS_CHANNEL_0);
break;
}
/* fallthrough */
case BOUNDS_CHANNEL_0 ... BOUNDS_CHANNEL_7:
case HYSTERESIS_CHANNEL_0 ... HYSTERESIS_CHANNEL_7:
case ENGINE_CONTROL:
case INTERRUPT_CONTROL:
case VGA_DETECT_CONTROL:
case CLOCK_CONTROL:
case INTERRUPT_SOURCE:
case COMPENSATING_AND_TRIMMING:
value = s->regs[reg];
break;
case DATA_CHANNEL_9_AND_8 ... DATA_CHANNEL_15_AND_14:
if (s->nr_channels <= 8) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: engine[%u]: "
"data register %u invalid, only 0...3 valid\n",
__func__, s->engine_id, reg - DATA_CHANNEL_1_AND_0);
break;
}
/* fallthrough */
case DATA_CHANNEL_1_AND_0 ... DATA_CHANNEL_7_AND_6:
value = read_channel_sample(s, reg);
/* Allow 16-bit reads of the data registers */
if (addr & 0x2) {
assert(size == 2);
value >>= 16;
}
break;
default:
qemu_log_mask(LOG_UNIMP, "%s: engine[%u]: 0x%" HWADDR_PRIx "\n",
__func__, s->engine_id, addr);
break;
}
trace_aspeed_adc_engine_read(s->engine_id, addr, value);
return value;
}
static void aspeed_adc_engine_write(void *opaque, hwaddr addr, uint64_t value,
unsigned int size)
{
AspeedADCEngineState *s = ASPEED_ADC_ENGINE(opaque);
int reg = TO_REG(addr);
uint32_t init = 0;
trace_aspeed_adc_engine_write(s->engine_id, addr, value);
switch (reg) {
case ENGINE_CONTROL:
init = !!(value & ASPEED_ADC_ENGINE_EN);
init *= ASPEED_ADC_ENGINE_INIT;
value &= ~ASPEED_ADC_ENGINE_INIT;
value |= init;
value &= ~ASPEED_ADC_ENGINE_AUTO_COMP;
break;
case INTERRUPT_CONTROL:
case VGA_DETECT_CONTROL:
case CLOCK_CONTROL:
break;
case DATA_CHANNEL_9_AND_8 ... DATA_CHANNEL_15_AND_14:
if (s->nr_channels <= 8) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: engine[%u]: "
"data register %u invalid, only 0...3 valid\n",
__func__, s->engine_id, reg - DATA_CHANNEL_1_AND_0);
return;
}
/* fallthrough */
case BOUNDS_CHANNEL_8 ... BOUNDS_CHANNEL_15:
if (s->nr_channels <= 8) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: engine[%u]: "
"bounds register %u invalid, only 0...7 valid\n",
__func__, s->engine_id, reg - BOUNDS_CHANNEL_0);
return;
}
/* fallthrough */
case DATA_CHANNEL_1_AND_0 ... DATA_CHANNEL_7_AND_6:
case BOUNDS_CHANNEL_0 ... BOUNDS_CHANNEL_7:
value &= ASPEED_ADC_LH_MASK;
break;
case HYSTERESIS_CHANNEL_8 ... HYSTERESIS_CHANNEL_15:
if (s->nr_channels <= 8) {
qemu_log_mask(LOG_GUEST_ERROR, "%s: engine[%u]: "
"hysteresis register %u invalid, only 0...7 valid\n",
__func__, s->engine_id, reg - HYSTERESIS_CHANNEL_0);
return;
}
/* fallthrough */
case HYSTERESIS_CHANNEL_0 ... HYSTERESIS_CHANNEL_7:
value &= (ASPEED_ADC_HYST_EN | ASPEED_ADC_LH_MASK);
break;
case INTERRUPT_SOURCE:
value &= 0xffff;
break;
case COMPENSATING_AND_TRIMMING:
value &= 0xf;
break;
default:
qemu_log_mask(LOG_UNIMP, "%s: engine[%u]: "
"0x%" HWADDR_PRIx " 0x%" PRIx64 "\n",
__func__, s->engine_id, addr, value);
break;
}
s->regs[reg] = value;
}
static const MemoryRegionOps aspeed_adc_engine_ops = {
.read = aspeed_adc_engine_read,
.write = aspeed_adc_engine_write,
.endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 2,
.max_access_size = 4,
.unaligned = false,
},
};
static const uint32_t aspeed_adc_resets[ASPEED_ADC_NR_REGS] = {
[ENGINE_CONTROL] = 0x00000000,
[INTERRUPT_CONTROL] = 0x00000000,
[VGA_DETECT_CONTROL] = 0x0000000f,
[CLOCK_CONTROL] = 0x0000000f,
};
static void aspeed_adc_engine_reset(DeviceState *dev)
{
AspeedADCEngineState *s = ASPEED_ADC_ENGINE(dev);
memcpy(s->regs, aspeed_adc_resets, sizeof(aspeed_adc_resets));
}
static void aspeed_adc_engine_realize(DeviceState *dev, Error **errp)
{
AspeedADCEngineState *s = ASPEED_ADC_ENGINE(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
g_autofree char *name = g_strdup_printf(TYPE_ASPEED_ADC_ENGINE ".%d",
s->engine_id);
assert(s->engine_id < 2);
sysbus_init_irq(sbd, &s->irq);
memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_adc_engine_ops, s, name,
ASPEED_ADC_ENGINE_MEMORY_REGION_SIZE);
sysbus_init_mmio(sbd, &s->mmio);
}
static const VMStateDescription vmstate_aspeed_adc_engine = {
.name = TYPE_ASPEED_ADC,
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(regs, AspeedADCEngineState, ASPEED_ADC_NR_REGS),
VMSTATE_END_OF_LIST(),
}
};
static Property aspeed_adc_engine_properties[] = {
DEFINE_PROP_UINT32("engine-id", AspeedADCEngineState, engine_id, 0),
DEFINE_PROP_UINT32("nr-channels", AspeedADCEngineState, nr_channels, 0),
DEFINE_PROP_END_OF_LIST(),
};
static void aspeed_adc_engine_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = aspeed_adc_engine_realize;
dc->reset = aspeed_adc_engine_reset;
device_class_set_props(dc, aspeed_adc_engine_properties);
dc->desc = "Aspeed Analog-to-Digital Engine";
dc->vmsd = &vmstate_aspeed_adc_engine;
}
static const TypeInfo aspeed_adc_engine_info = {
.name = TYPE_ASPEED_ADC_ENGINE,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(AspeedADCEngineState),
.class_init = aspeed_adc_engine_class_init,
};
static void aspeed_adc_instance_init(Object *obj)
{
AspeedADCState *s = ASPEED_ADC(obj);
AspeedADCClass *aac = ASPEED_ADC_GET_CLASS(obj);
uint32_t nr_channels = ASPEED_ADC_NR_CHANNELS / aac->nr_engines;
for (int i = 0; i < aac->nr_engines; i++) {
AspeedADCEngineState *engine = &s->engines[i];
object_initialize_child(obj, "engine[*]", engine,
TYPE_ASPEED_ADC_ENGINE);
qdev_prop_set_uint32(DEVICE(engine), "engine-id", i);
qdev_prop_set_uint32(DEVICE(engine), "nr-channels", nr_channels);
}
}
static void aspeed_adc_set_irq(void *opaque, int n, int level)
{
AspeedADCState *s = opaque;
AspeedADCClass *aac = ASPEED_ADC_GET_CLASS(s);
uint32_t pending = 0;
/* TODO: update Global IRQ status register on AST2600 (Need specs) */
for (int i = 0; i < aac->nr_engines; i++) {
uint32_t irq_status = s->engines[i].regs[INTERRUPT_CONTROL] & 0xFF;
pending |= irq_status << (i * 8);
}
qemu_set_irq(s->irq, !!pending);
}
static void aspeed_adc_realize(DeviceState *dev, Error **errp)
{
AspeedADCState *s = ASPEED_ADC(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
AspeedADCClass *aac = ASPEED_ADC_GET_CLASS(dev);
qdev_init_gpio_in_named_with_opaque(DEVICE(sbd), aspeed_adc_set_irq,
s, NULL, aac->nr_engines);
sysbus_init_irq(sbd, &s->irq);
memory_region_init(&s->mmio, OBJECT(s), TYPE_ASPEED_ADC,
ASPEED_ADC_MEMORY_REGION_SIZE);
sysbus_init_mmio(sbd, &s->mmio);
for (int i = 0; i < aac->nr_engines; i++) {
Object *eng = OBJECT(&s->engines[i]);
if (!sysbus_realize(SYS_BUS_DEVICE(eng), errp)) {
return;
}
sysbus_connect_irq(SYS_BUS_DEVICE(eng), 0,
qdev_get_gpio_in(DEVICE(sbd), i));
memory_region_add_subregion(&s->mmio,
i * ASPEED_ADC_ENGINE_MEMORY_REGION_SIZE,
&s->engines[i].mmio);
}
}
static void aspeed_adc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedADCClass *aac = ASPEED_ADC_CLASS(klass);
dc->realize = aspeed_adc_realize;
dc->desc = "Aspeed Analog-to-Digital Converter";
aac->nr_engines = 1;
}
static void aspeed_2600_adc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
AspeedADCClass *aac = ASPEED_ADC_CLASS(klass);
dc->desc = "ASPEED 2600 ADC Controller";
aac->nr_engines = 2;
}
static const TypeInfo aspeed_adc_info = {
.name = TYPE_ASPEED_ADC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_init = aspeed_adc_instance_init,
.instance_size = sizeof(AspeedADCState),
.class_init = aspeed_adc_class_init,
.class_size = sizeof(AspeedADCClass),
.abstract = true,
};
static const TypeInfo aspeed_2400_adc_info = {
.name = TYPE_ASPEED_2400_ADC,
.parent = TYPE_ASPEED_ADC,
};
static const TypeInfo aspeed_2500_adc_info = {
.name = TYPE_ASPEED_2500_ADC,
.parent = TYPE_ASPEED_ADC,
};
static const TypeInfo aspeed_2600_adc_info = {
.name = TYPE_ASPEED_2600_ADC,
.parent = TYPE_ASPEED_ADC,
.class_init = aspeed_2600_adc_class_init,
};
static void aspeed_adc_register_types(void)
{
type_register_static(&aspeed_adc_engine_info);
type_register_static(&aspeed_adc_info);
type_register_static(&aspeed_2400_adc_info);
type_register_static(&aspeed_2500_adc_info);
type_register_static(&aspeed_2600_adc_info);
}
type_init(aspeed_adc_register_types);

View File

@ -1,4 +1,5 @@
softmmu_ss.add(when: 'CONFIG_STM32F2XX_ADC', if_true: files('stm32f2xx_adc.c'))
softmmu_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_adc.c'))
softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_adc.c'))
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq-xadc.c'))
softmmu_ss.add(when: 'CONFIG_MAX111X', if_true: files('max111x.c'))

View File

@ -3,3 +3,6 @@
# npcm7xx_adc.c
npcm7xx_adc_read(const char *id, uint64_t offset, uint32_t value) " %s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
npcm7xx_adc_write(const char *id, uint64_t offset, uint32_t value) "%s offset: 0x%04" PRIx64 " value 0x%04" PRIx32
aspeed_adc_engine_read(uint32_t engine_id, uint64_t addr, uint64_t value) "engine[%u] 0x%" PRIx64 " 0x%" PRIx64
aspeed_adc_engine_write(uint32_t engine_id, uint64_t addr, uint64_t value) "engine[%u] 0x%" PRIx64 " 0x%" PRIx64

View File

@ -274,18 +274,17 @@ static void aspeed_board_init_flashes(AspeedSMCState *s,
int i ;
for (i = 0; i < s->num_cs; ++i) {
AspeedSMCFlash *fl = &s->flashes[i];
DriveInfo *dinfo = drive_get_next(IF_MTD);
qemu_irq cs_line;
DeviceState *dev;
fl->flash = qdev_new(flashtype);
dev = qdev_new(flashtype);
if (dinfo) {
qdev_prop_set_drive(fl->flash, "drive",
blk_by_legacy_dinfo(dinfo));
qdev_prop_set_drive(dev, "drive", blk_by_legacy_dinfo(dinfo));
}
qdev_realize_and_unref(fl->flash, BUS(s->spi), &error_fatal);
qdev_realize_and_unref(dev, BUS(s->spi), &error_fatal);
cs_line = qdev_get_gpio_in_named(fl->flash, SSI_GPIO_CS, 0);
cs_line = qdev_get_gpio_in_named(dev, SSI_GPIO_CS, 0);
sysbus_connect_irq(SYS_BUS_DEVICE(s), i + 1, cs_line);
}
}
@ -377,6 +376,7 @@ static void aspeed_machine_init(MachineState *machine)
if (drive0) {
AspeedSMCFlash *fl = &bmc->soc.fmc.flashes[0];
MemoryRegion *boot_rom = g_new(MemoryRegion, 1);
uint64_t size = memory_region_size(&fl->mmio);
/*
* create a ROM region using the default mapping window size of
@ -386,15 +386,15 @@ static void aspeed_machine_init(MachineState *machine)
*/
if (ASPEED_MACHINE(machine)->mmio_exec) {
memory_region_init_alias(boot_rom, NULL, "aspeed.boot_rom",
&fl->mmio, 0, fl->size);
&fl->mmio, 0, size);
memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
boot_rom);
} else {
memory_region_init_rom(boot_rom, NULL, "aspeed.boot_rom",
fl->size, &error_abort);
size, &error_abort);
memory_region_add_subregion(get_system_memory(), FIRMWARE_ADDR,
boot_rom);
write_boot_rom(drive0, FIRMWARE_ADDR, fl->size, &error_abort);
write_boot_rom(drive0, FIRMWARE_ADDR, size, &error_abort);
}
}

View File

@ -148,6 +148,9 @@ static void aspeed_soc_ast2600_init(Object *obj)
snprintf(typename, sizeof(typename), "aspeed.timer-%s", socname);
object_initialize_child(obj, "timerctrl", &s->timerctrl, typename);
snprintf(typename, sizeof(typename), "aspeed.adc-%s", socname);
object_initialize_child(obj, "adc", &s->adc, typename);
snprintf(typename, sizeof(typename), "aspeed.i2c-%s", socname);
object_initialize_child(obj, "i2c", &s->i2c, typename);
@ -322,6 +325,14 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
}
/* ADC */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc), errp)) {
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->adc), 0, sc->memmap[ASPEED_DEV_ADC]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
aspeed_soc_get_irq(s, ASPEED_DEV_ADC));
/* UART - attach an 8250 to the IO space as our UART */
serial_mm_init(get_system_memory(), sc->memmap[s->uart_default], 2,
aspeed_soc_get_irq(s, s->uart_default), 38400,
@ -337,11 +348,8 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
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_DEV_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);
/* The AST2600 I2C controller has one IRQ per bus. */
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c.busses[i]), 0, irq);
}
/* FMC, The number of CS is set at the board level */
@ -352,7 +360,7 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 0, sc->memmap[ASPEED_DEV_FMC]);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 1,
s->fmc.ctrl->flash_window_base);
ASPEED_SMC_GET_CLASS(&s->fmc)->flash_window_base);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
aspeed_soc_get_irq(s, ASPEED_DEV_FMC));
@ -367,7 +375,7 @@ static void aspeed_soc_ast2600_realize(DeviceState *dev, Error **errp)
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0,
sc->memmap[ASPEED_DEV_SPI1 + i]);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 1,
s->spi[i].ctrl->flash_window_base);
ASPEED_SMC_GET_CLASS(&s->spi[i])->flash_window_base);
}
/* EHCI */

View File

@ -162,6 +162,9 @@ static void aspeed_soc_init(Object *obj)
snprintf(typename, sizeof(typename), "aspeed.timer-%s", socname);
object_initialize_child(obj, "timerctrl", &s->timerctrl, typename);
snprintf(typename, sizeof(typename), "aspeed.adc-%s", socname);
object_initialize_child(obj, "adc", &s->adc, typename);
snprintf(typename, sizeof(typename), "aspeed.i2c-%s", socname);
object_initialize_child(obj, "i2c", &s->i2c, typename);
@ -287,6 +290,14 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(&s->timerctrl), i, irq);
}
/* ADC */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->adc), errp)) {
return;
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->adc), 0, sc->memmap[ASPEED_DEV_ADC]);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->adc), 0,
aspeed_soc_get_irq(s, ASPEED_DEV_ADC));
/* UART - attach an 8250 to the IO space as our UART */
serial_mm_init(get_system_memory(), sc->memmap[s->uart_default], 2,
aspeed_soc_get_irq(s, s->uart_default), 38400,
@ -310,7 +321,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
}
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 0, sc->memmap[ASPEED_DEV_FMC]);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->fmc), 1,
s->fmc.ctrl->flash_window_base);
ASPEED_SMC_GET_CLASS(&s->fmc)->flash_window_base);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->fmc), 0,
aspeed_soc_get_irq(s, ASPEED_DEV_FMC));
@ -323,7 +334,7 @@ static void aspeed_soc_realize(DeviceState *dev, Error **errp)
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 0,
sc->memmap[ASPEED_DEV_SPI1 + i]);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->spi[i]), 1,
s->spi[i].ctrl->flash_window_base);
ASPEED_SMC_GET_CLASS(&s->spi[i])->flash_window_base);
}
/* EHCI */

View File

@ -16,11 +16,7 @@
#include "hw/irq.h"
#include "migration/vmstate.h"
#define GPIOS_PER_REG 32
#define GPIOS_PER_SET GPIOS_PER_REG
#define GPIO_PIN_GAP_SIZE 4
#define GPIOS_PER_GROUP 8
#define GPIO_GROUP_SHIFT 3
/* GPIO Source Types */
#define ASPEED_CMD_SRC_MASK 0x01010101
@ -259,7 +255,7 @@ static void aspeed_gpio_update(AspeedGPIOState *s, GPIOSets *regs,
diff = old ^ new;
if (diff) {
for (gpio = 0; gpio < GPIOS_PER_REG; gpio++) {
for (gpio = 0; gpio < ASPEED_GPIOS_PER_SET; gpio++) {
uint32_t mask = 1 << gpio;
/* If the gpio needs to be updated... */
@ -283,8 +279,7 @@ static void aspeed_gpio_update(AspeedGPIOState *s, GPIOSets *regs,
if (direction & mask) {
/* ...trigger the line-state IRQ */
ptrdiff_t set = aspeed_gpio_set_idx(s, regs);
size_t offset = set * GPIOS_PER_SET + gpio;
qemu_set_irq(s->gpios[offset], !!(new & mask));
qemu_set_irq(s->gpios[set][gpio], !!(new & mask));
} else {
/* ...otherwise if we meet the line's current IRQ policy... */
if (aspeed_evaluate_irq(regs, old & mask, gpio)) {
@ -297,21 +292,6 @@ static void aspeed_gpio_update(AspeedGPIOState *s, GPIOSets *regs,
qemu_set_irq(s->irq, !!(s->pending));
}
static uint32_t aspeed_adjust_pin(AspeedGPIOState *s, uint32_t pin)
{
AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
/*
* The 2500 has a 4 pin gap in group AB and the 2400 has a 4 pin
* gap in group Y (and only four pins in AB but this is the last group so
* it doesn't matter).
*/
if (agc->gap && pin >= agc->gap) {
pin += GPIO_PIN_GAP_SIZE;
}
return pin;
}
static bool aspeed_gpio_get_pin_level(AspeedGPIOState *s, uint32_t set_idx,
uint32_t pin)
{
@ -367,7 +347,7 @@ static uint32_t update_value_control_source(GPIOSets *regs, uint32_t old_value,
uint32_t new_value = 0;
/* for each group in set */
for (i = 0; i < GPIOS_PER_REG; i += GPIOS_PER_GROUP) {
for (i = 0; i < ASPEED_GPIOS_PER_SET; i += GPIOS_PER_GROUP) {
cmd_source = extract32(regs->cmd_source_0, i, 1)
| (extract32(regs->cmd_source_1, i, 1) << 1);
@ -637,7 +617,7 @@ static void aspeed_gpio_write(void *opaque, hwaddr offset, uint64_t data,
* bidirectional | 1 | 1 | data
* input only | 1 | 0 | 0
* output only | 0 | 1 | 1
* no pin / gap | 0 | 0 | 0
* no pin | 0 | 0 | 0
*
* which is captured by:
* data = ( data | ~input) & output;
@ -779,7 +759,7 @@ static void aspeed_gpio_set_pin(Object *obj, Visitor *v, const char *name,
}
/****************** Setup functions ******************/
static const GPIOSetProperties ast2400_set_props[] = {
static const GPIOSetProperties ast2400_set_props[ASPEED_GPIO_MAX_NR_SETS] = {
[0] = {0xffffffff, 0xffffffff, {"A", "B", "C", "D"} },
[1] = {0xffffffff, 0xffffffff, {"E", "F", "G", "H"} },
[2] = {0xffffffff, 0xffffffff, {"I", "J", "K", "L"} },
@ -789,28 +769,28 @@ static const GPIOSetProperties ast2400_set_props[] = {
[6] = {0x0000000f, 0x0fffff0f, {"Y", "Z", "AA", "AB"} },
};
static const GPIOSetProperties ast2500_set_props[] = {
static const GPIOSetProperties ast2500_set_props[ASPEED_GPIO_MAX_NR_SETS] = {
[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] = {0xffffff0f, 0x0fffff0f, {"Y", "Z", "AA", "AB"} },
[6] = {0x0fffffff, 0x0fffffff, {"Y", "Z", "AA", "AB"} },
[7] = {0x000000ff, 0x000000ff, {"AC"} },
};
static GPIOSetProperties ast2600_3_3v_set_props[] = {
static GPIOSetProperties ast2600_3_3v_set_props[ASPEED_GPIO_MAX_NR_SETS] = {
[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", "", ""} },
[4] = {0xffffffff, 0x00ffffff, {"Q", "R", "S", "T"} },
[5] = {0xffffffff, 0xffffff00, {"U", "V", "W", "X"} },
[6] = {0x0000ffff, 0x0000ffff, {"Y", "Z"} },
};
static GPIOSetProperties ast2600_1_8v_set_props[] = {
static GPIOSetProperties ast2600_1_8v_set_props[ASPEED_GPIO_MAX_NR_SETS] = {
[0] = {0xffffffff, 0xffffffff, {"18A", "18B", "18C", "18D"} },
[1] = {0x0000000f, 0x0000000f, {"18E"} },
};
@ -836,14 +816,20 @@ static void aspeed_gpio_realize(DeviceState *dev, Error **errp)
AspeedGPIOState *s = ASPEED_GPIO(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
int pin;
/* Interrupt parent line */
sysbus_init_irq(sbd, &s->irq);
/* Individual GPIOs */
for (pin = 0; pin < agc->nr_gpio_pins; pin++) {
sysbus_init_irq(sbd, &s->gpios[pin]);
for (int i = 0; i < ASPEED_GPIO_MAX_NR_SETS; i++) {
const GPIOSetProperties *props = &agc->props[i];
uint32_t skip = ~(props->input | props->output);
for (int j = 0; j < ASPEED_GPIOS_PER_SET; j++) {
if (skip >> j & 1) {
continue;
}
sysbus_init_irq(sbd, &s->gpios[i][j]);
}
}
memory_region_init_io(&s->iomem, OBJECT(s), &aspeed_gpio_ops, s,
@ -856,20 +842,22 @@ static void aspeed_gpio_init(Object *obj)
{
AspeedGPIOState *s = ASPEED_GPIO(obj);
AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);
int pin;
for (pin = 0; pin < agc->nr_gpio_pins; pin++) {
char *name;
int set_idx = pin / GPIOS_PER_SET;
int pin_idx = aspeed_adjust_pin(s, pin) - (set_idx * GPIOS_PER_SET);
int group_idx = pin_idx >> GPIO_GROUP_SHIFT;
const GPIOSetProperties *props = &agc->props[set_idx];
name = g_strdup_printf("gpio%s%d", props->group_label[group_idx],
pin_idx % GPIOS_PER_GROUP);
object_property_add(obj, name, "bool", aspeed_gpio_get_pin,
aspeed_gpio_set_pin, NULL, NULL);
g_free(name);
for (int i = 0; i < ASPEED_GPIO_MAX_NR_SETS; i++) {
const GPIOSetProperties *props = &agc->props[i];
uint32_t skip = ~(props->input | props->output);
for (int j = 0; j < ASPEED_GPIOS_PER_SET; j++) {
if (skip >> j & 1) {
continue;
}
int group_idx = j / GPIOS_PER_GROUP;
int pin_idx = j % GPIOS_PER_GROUP;
const char *group = &props->group_label[group_idx][0];
char *name = g_strdup_printf("gpio%s%d", group, pin_idx);
object_property_add(obj, name, "bool", aspeed_gpio_get_pin,
aspeed_gpio_set_pin, NULL, NULL);
g_free(name);
}
}
}
@ -926,7 +914,6 @@ static void aspeed_gpio_ast2400_class_init(ObjectClass *klass, void *data)
agc->props = ast2400_set_props;
agc->nr_gpio_pins = 216;
agc->nr_gpio_sets = 7;
agc->gap = 196;
agc->reg_table = aspeed_3_3v_gpios;
}
@ -937,7 +924,6 @@ static void aspeed_gpio_2500_class_init(ObjectClass *klass, void *data)
agc->props = ast2500_set_props;
agc->nr_gpio_pins = 228;
agc->nr_gpio_sets = 8;
agc->gap = 220;
agc->reg_table = aspeed_3_3v_gpios;
}

View File

@ -740,20 +740,20 @@ static const VMStateDescription aspeed_i2c_vmstate = {
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;
}
static void aspeed_i2c_instance_init(Object *obj)
{
AspeedI2CState *s = ASPEED_I2C(obj);
AspeedI2CClass *aic = ASPEED_I2C_GET_CLASS(s);
int 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;
s->busses[i].buf = 0;
s->busses[i].dma_addr = 0;
s->busses[i].dma_len = 0;
i2c_end_transfer(s->busses[i].bus);
object_initialize_child(obj, "bus[*]", &s->busses[i],
TYPE_ASPEED_I2C_BUS);
}
}
@ -791,17 +791,21 @@ static void aspeed_i2c_realize(DeviceState *dev, Error **errp)
sysbus_init_mmio(sbd, &s->iomem);
for (i = 0; i < aic->num_busses; i++) {
char name[32];
Object *bus = OBJECT(&s->busses[i]);
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,
aic->reg_size);
if (!object_property_set_link(bus, "controller", OBJECT(s), errp)) {
return;
}
if (!object_property_set_uint(bus, "bus-id", i, errp)) {
return;
}
if (!sysbus_realize(SYS_BUS_DEVICE(bus), errp)) {
return;
}
memory_region_add_subregion(&s->iomem, aic->reg_size * (i + offset),
&s->busses[i].mr);
}
@ -841,12 +845,72 @@ static void aspeed_i2c_class_init(ObjectClass *klass, void *data)
static const TypeInfo aspeed_i2c_info = {
.name = TYPE_ASPEED_I2C,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_init = aspeed_i2c_instance_init,
.instance_size = sizeof(AspeedI2CState),
.class_init = aspeed_i2c_class_init,
.class_size = sizeof(AspeedI2CClass),
.abstract = true,
};
static void aspeed_i2c_bus_reset(DeviceState *dev)
{
AspeedI2CBus *s = ASPEED_I2C_BUS(dev);
s->intr_ctrl = 0;
s->intr_status = 0;
s->cmd = 0;
s->buf = 0;
s->dma_addr = 0;
s->dma_len = 0;
i2c_end_transfer(s->bus);
}
static void aspeed_i2c_bus_realize(DeviceState *dev, Error **errp)
{
AspeedI2CBus *s = ASPEED_I2C_BUS(dev);
AspeedI2CClass *aic;
g_autofree char *name = g_strdup_printf(TYPE_ASPEED_I2C_BUS ".%d", s->id);
if (!s->controller) {
error_setg(errp, TYPE_ASPEED_I2C_BUS ": 'controller' link not set");
return;
}
aic = ASPEED_I2C_GET_CLASS(s->controller);
sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
s->bus = i2c_init_bus(dev, name);
memory_region_init_io(&s->mr, OBJECT(s), &aspeed_i2c_bus_ops,
s, name, aic->reg_size);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mr);
}
static Property aspeed_i2c_bus_properties[] = {
DEFINE_PROP_UINT8("bus-id", AspeedI2CBus, id, 0),
DEFINE_PROP_LINK("controller", AspeedI2CBus, controller, TYPE_ASPEED_I2C,
AspeedI2CState *),
DEFINE_PROP_END_OF_LIST(),
};
static void aspeed_i2c_bus_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->desc = "Aspeed I2C Bus";
dc->realize = aspeed_i2c_bus_realize;
dc->reset = aspeed_i2c_bus_reset;
device_class_set_props(dc, aspeed_i2c_bus_properties);
}
static const TypeInfo aspeed_i2c_bus_info = {
.name = TYPE_ASPEED_I2C_BUS,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(AspeedI2CBus),
.class_init = aspeed_i2c_bus_class_init,
};
static qemu_irq aspeed_2400_i2c_bus_get_irq(AspeedI2CBus *bus)
{
return bus->controller->irq;
@ -951,6 +1015,7 @@ static const TypeInfo aspeed_2600_i2c_info = {
static void aspeed_i2c_register_types(void)
{
type_register_static(&aspeed_i2c_bus_info);
type_register_static(&aspeed_i2c_info);
type_register_static(&aspeed_2400_i2c_info);
type_register_static(&aspeed_2500_i2c_info);

File diff suppressed because it is too large Load Diff

View File

@ -5,3 +5,7 @@ cmsdk_apb_watchdog_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK AP
cmsdk_apb_watchdog_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
cmsdk_apb_watchdog_reset(void) "CMSDK APB watchdog: reset"
cmsdk_apb_watchdog_lock(uint32_t lock) "CMSDK APB watchdog: lock %" PRIu32
# wdt-aspeed.c
aspeed_wdt_read(uint64_t addr, uint32_t size) "@0x%" PRIx64 " size=%d"
aspeed_wdt_write(uint64_t addr, uint32_t size, uint64_t data) "@0x%" PRIx64 " size=%d value=0x%"PRIx64

View File

@ -19,6 +19,7 @@
#include "hw/sysbus.h"
#include "hw/watchdog/wdt_aspeed.h"
#include "migration/vmstate.h"
#include "trace.h"
#define WDT_STATUS (0x00 / 4)
#define WDT_RELOAD_VALUE (0x04 / 4)
@ -60,6 +61,8 @@ static uint64_t aspeed_wdt_read(void *opaque, hwaddr offset, unsigned size)
{
AspeedWDTState *s = ASPEED_WDT(opaque);
trace_aspeed_wdt_read(offset, size);
offset >>= 2;
switch (offset) {
@ -140,6 +143,8 @@ static void aspeed_wdt_write(void *opaque, hwaddr offset, uint64_t data,
AspeedWDTClass *awc = ASPEED_WDT_GET_CLASS(s);
bool enable;
trace_aspeed_wdt_write(offset, size, data);
offset >>= 2;
switch (offset) {

View File

@ -0,0 +1,55 @@
/*
* Aspeed ADC
*
* Copyright 2017-2021 IBM Corp.
*
* Andrew Jeffery <andrew@aj.id.au>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef HW_ADC_ASPEED_ADC_H
#define HW_ADC_ASPEED_ADC_H
#include "hw/sysbus.h"
#define TYPE_ASPEED_ADC "aspeed.adc"
#define TYPE_ASPEED_2400_ADC TYPE_ASPEED_ADC "-ast2400"
#define TYPE_ASPEED_2500_ADC TYPE_ASPEED_ADC "-ast2500"
#define TYPE_ASPEED_2600_ADC TYPE_ASPEED_ADC "-ast2600"
OBJECT_DECLARE_TYPE(AspeedADCState, AspeedADCClass, ASPEED_ADC)
#define TYPE_ASPEED_ADC_ENGINE "aspeed.adc.engine"
OBJECT_DECLARE_SIMPLE_TYPE(AspeedADCEngineState, ASPEED_ADC_ENGINE)
#define ASPEED_ADC_NR_CHANNELS 16
#define ASPEED_ADC_NR_REGS (0xD0 >> 2)
struct AspeedADCEngineState {
/* <private> */
SysBusDevice parent;
MemoryRegion mmio;
qemu_irq irq;
uint32_t engine_id;
uint32_t nr_channels;
uint32_t regs[ASPEED_ADC_NR_REGS];
};
struct AspeedADCState {
/* <private> */
SysBusDevice parent;
MemoryRegion mmio;
qemu_irq irq;
AspeedADCEngineState engines[2];
};
struct AspeedADCClass {
SysBusDeviceClass parent_class;
uint32_t nr_engines;
};
#endif /* HW_ADC_ASPEED_ADC_H */

View File

@ -15,6 +15,7 @@
#include "hw/cpu/a15mpcore.h"
#include "hw/intc/aspeed_vic.h"
#include "hw/misc/aspeed_scu.h"
#include "hw/adc/aspeed_adc.h"
#include "hw/misc/aspeed_sdmc.h"
#include "hw/misc/aspeed_xdma.h"
#include "hw/timer/aspeed_timer.h"
@ -53,6 +54,7 @@ struct AspeedSoCState {
AspeedSCUState scu;
AspeedHACEState hace;
AspeedXDMAState xdma;
AspeedADCState adc;
AspeedSMCState fmc;
AspeedSMCState spi[ASPEED_SPIS_NUM];
EHCISysBusState ehci[ASPEED_EHCIS_NUM];

View File

@ -17,9 +17,9 @@
OBJECT_DECLARE_TYPE(AspeedGPIOState, AspeedGPIOClass, ASPEED_GPIO)
#define ASPEED_GPIO_MAX_NR_SETS 8
#define ASPEED_GPIOS_PER_SET 32
#define ASPEED_REGS_PER_BANK 14
#define ASPEED_GPIO_MAX_NR_REGS (ASPEED_REGS_PER_BANK * ASPEED_GPIO_MAX_NR_SETS)
#define ASPEED_GPIO_NR_PINS 228
#define ASPEED_GROUPS_PER_SET 4
#define ASPEED_GPIO_NR_DEBOUNCE_REGS 3
#define ASPEED_CHARS_PER_GROUP_LABEL 4
@ -60,7 +60,6 @@ struct AspeedGPIOClass {
const GPIOSetProperties *props;
uint32_t nr_gpio_pins;
uint32_t nr_gpio_sets;
uint32_t gap;
const AspeedGPIOReg *reg_table;
};
@ -72,7 +71,7 @@ struct AspeedGPIOState {
MemoryRegion iomem;
int pending;
qemu_irq irq;
qemu_irq gpios[ASPEED_GPIO_NR_PINS];
qemu_irq gpios[ASPEED_GPIO_MAX_NR_SETS][ASPEED_GPIOS_PER_SET];
/* Parallel GPIO Registers */
uint32_t debounce_regs[ASPEED_GPIO_NR_DEBOUNCE_REGS];

View File

@ -36,7 +36,11 @@ OBJECT_DECLARE_TYPE(AspeedI2CState, AspeedI2CClass, ASPEED_I2C)
struct AspeedI2CState;
typedef struct AspeedI2CBus {
#define TYPE_ASPEED_I2C_BUS "aspeed.i2c.bus"
OBJECT_DECLARE_SIMPLE_TYPE(AspeedI2CBus, ASPEED_I2C_BUS)
struct AspeedI2CBus {
SysBusDevice parent_obj;
struct AspeedI2CState *controller;
MemoryRegion mr;
@ -54,7 +58,7 @@ typedef struct AspeedI2CBus {
uint32_t pool_ctrl;
uint32_t dma_addr;
uint32_t dma_len;
} AspeedI2CBus;
};
struct AspeedI2CState {
SysBusDevice parent_obj;

View File

@ -29,66 +29,33 @@
#include "hw/sysbus.h"
#include "qom/object.h"
typedef struct AspeedSegments {
hwaddr addr;
uint32_t size;
} AspeedSegments;
struct AspeedSMCState;
typedef struct AspeedSMCController {
const char *name;
uint8_t r_conf;
uint8_t r_ce_ctrl;
uint8_t r_ctrl0;
uint8_t r_timings;
uint8_t nregs_timings;
uint8_t conf_enable_w0;
uint8_t max_peripherals;
const AspeedSegments *segments;
hwaddr flash_window_base;
uint32_t flash_window_size;
uint32_t features;
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);
void (*dma_ctrl)(struct AspeedSMCState *s, uint32_t value);
} AspeedSMCController;
typedef struct AspeedSMCFlash {
#define TYPE_ASPEED_SMC_FLASH "aspeed.smc.flash"
OBJECT_DECLARE_SIMPLE_TYPE(AspeedSMCFlash, ASPEED_SMC_FLASH)
struct AspeedSMCFlash {
SysBusDevice parent_obj;
struct AspeedSMCState *controller;
uint8_t id;
uint32_t size;
uint8_t cs;
MemoryRegion mmio;
DeviceState *flash;
} AspeedSMCFlash;
};
#define TYPE_ASPEED_SMC "aspeed.smc"
OBJECT_DECLARE_TYPE(AspeedSMCState, AspeedSMCClass, ASPEED_SMC)
struct AspeedSMCClass {
SysBusDevice parent_obj;
const AspeedSMCController *ctrl;
};
#define ASPEED_SMC_R_MAX (0x100 / 4)
#define ASPEED_SMC_CS_MAX 5
struct AspeedSMCState {
SysBusDevice parent_obj;
const AspeedSMCController *ctrl;
MemoryRegion mmio;
MemoryRegion mmio_flash;
MemoryRegion mmio_flash_alias;
qemu_irq irq;
int irqline;
uint32_t num_cs;
qemu_irq *cs_lines;
@ -109,10 +76,41 @@ struct AspeedSMCState {
MemoryRegion *dram_mr;
AddressSpace dram_as;
AspeedSMCFlash *flashes;
AspeedSMCFlash flashes[ASPEED_SMC_CS_MAX];
uint8_t snoop_index;
uint8_t snoop_dummies;
};
typedef struct AspeedSegments {
hwaddr addr;
uint32_t size;
} AspeedSegments;
struct AspeedSMCClass {
SysBusDeviceClass parent_obj;
uint8_t r_conf;
uint8_t r_ce_ctrl;
uint8_t r_ctrl0;
uint8_t r_timings;
uint8_t nregs_timings;
uint8_t conf_enable_w0;
uint8_t max_peripherals;
const uint32_t *resets;
const AspeedSegments *segments;
hwaddr flash_window_base;
uint32_t flash_window_size;
uint32_t features;
hwaddr dma_flash_mask;
hwaddr dma_dram_mask;
uint32_t nregs;
uint32_t (*segment_to_reg)(const AspeedSMCState *s,
const AspeedSegments *seg);
void (*reg_to_segment)(const AspeedSMCState *s, uint32_t reg,
AspeedSegments *seg);
void (*dma_ctrl)(AspeedSMCState *s, uint32_t value);
int (*addr_width)(const AspeedSMCState *s);
};
#endif /* ASPEED_SMC_H */