diff options
Diffstat (limited to 'hw/misc')
-rw-r--r-- | hw/misc/armsse-cpuid.c | 2 | ||||
-rw-r--r-- | hw/misc/armsse-mhu.c | 2 | ||||
-rw-r--r-- | hw/misc/iotkit-sysctl.c | 2 | ||||
-rw-r--r-- | hw/misc/iotkit-sysinfo.c | 2 | ||||
-rw-r--r-- | hw/misc/mps2-fpgaio.c | 43 | ||||
-rw-r--r-- | hw/misc/mps2-scc.c | 93 |
6 files changed, 119 insertions, 25 deletions
diff --git a/hw/misc/armsse-cpuid.c b/hw/misc/armsse-cpuid.c index d58138dc28..e785a09051 100644 --- a/hw/misc/armsse-cpuid.c +++ b/hw/misc/armsse-cpuid.c @@ -12,7 +12,7 @@ /* * This is a model of the "CPU_IDENTITY" register block which is part of the * Arm SSE-200 and documented in - * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf + * https://developer.arm.com/documentation/101104/latest/ * * It consists of one read-only CPUID register (set by QOM property), plus the * usual ID registers. diff --git a/hw/misc/armsse-mhu.c b/hw/misc/armsse-mhu.c index a45d97fada..0be7f0fc87 100644 --- a/hw/misc/armsse-mhu.c +++ b/hw/misc/armsse-mhu.c @@ -12,7 +12,7 @@ /* * This is a model of the Message Handling Unit (MHU) which is part of the * Arm SSE-200 and documented in - * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf + * https://developer.arm.com/documentation/101104/latest/ */ #include "qemu/osdep.h" diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c index 964b48c74d..222511c4b0 100644 --- a/hw/misc/iotkit-sysctl.c +++ b/hw/misc/iotkit-sysctl.c @@ -12,7 +12,7 @@ /* * This is a model of the "system control element" which is part of the * Arm IoTKit and documented in - * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html + * https://developer.arm.com/documentation/ecm0601256/latest * Specifically, it implements the "system control register" blocks. */ diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c index b2dcfc4376..52e70053df 100644 --- a/hw/misc/iotkit-sysinfo.c +++ b/hw/misc/iotkit-sysinfo.c @@ -12,7 +12,7 @@ /* * This is a model of the "system information block" which is part of the * Arm IoTKit and documented in - * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html + * https://developer.arm.com/documentation/ecm0601256/latest * It consists of 2 read-only version/config registers, plus the * usual ID registers. */ diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c index 6af0e8f837..f3db88ddcc 100644 --- a/hw/misc/mps2-fpgaio.c +++ b/hw/misc/mps2-fpgaio.c @@ -12,7 +12,7 @@ /* This is a model of the "FPGA system control and I/O" block found * in the AN505 FPGA image for the MPS2 devboard. * It is documented in AN505: - * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html + * https://developer.arm.com/documentation/dai0505/latest/ */ #include "qemu/osdep.h" @@ -35,6 +35,7 @@ REG32(CLK100HZ, 0x14) REG32(COUNTER, 0x18) REG32(PRESCALE, 0x1c) REG32(PSCNTR, 0x20) +REG32(SWITCH, 0x28) REG32(MISC, 0x4c) static uint32_t counter_from_tickoff(int64_t now, int64_t tick_offset, int frq) @@ -156,7 +157,15 @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size) resync_counter(s); r = s->pscntr; break; + case A_SWITCH: + if (!s->has_switches) { + goto bad_offset; + } + /* User-togglable board switches. We don't model that, so report 0. */ + r = 0; + break; default: + bad_offset: qemu_log_mask(LOG_GUEST_ERROR, "MPS2 FPGAIO read: bad offset %x\n", (int) offset); r = 0; @@ -177,9 +186,14 @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value, switch (offset) { case A_LED0: - s->led0 = value & 0x3; - led_set_state(s->led[0], value & 0x01); - led_set_state(s->led[1], value & 0x02); + if (s->num_leds != 0) { + uint32_t i; + + s->led0 = value & MAKE_64BIT_MASK(0, s->num_leds); + for (i = 0; i < s->num_leds; i++) { + led_set_state(s->led[i], value & (1 << i)); + } + } break; case A_PRESCALE: resync_counter(s); @@ -238,7 +252,7 @@ static void mps2_fpgaio_reset(DeviceState *dev) s->pscntr = 0; s->pscntr_sync_ticks = now; - for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) { + for (size_t i = 0; i < s->num_leds; i++) { device_cold_reset(DEVICE(s->led[i])); } } @@ -256,11 +270,19 @@ static void mps2_fpgaio_init(Object *obj) static void mps2_fpgaio_realize(DeviceState *dev, Error **errp) { MPS2FPGAIO *s = MPS2_FPGAIO(dev); + uint32_t i; - s->led[0] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH, - LED_COLOR_GREEN, "USERLED0"); - s->led[1] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH, - LED_COLOR_GREEN, "USERLED1"); + if (s->num_leds > MPS2FPGAIO_MAX_LEDS) { + error_setg(errp, "num-leds cannot be greater than %d", + MPS2FPGAIO_MAX_LEDS); + return; + } + + for (i = 0; i < s->num_leds; i++) { + g_autofree char *ledname = g_strdup_printf("USERLED%d", i); + s->led[i] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH, + LED_COLOR_GREEN, ledname); + } } static bool mps2_fpgaio_counters_needed(void *opaque) @@ -303,6 +325,9 @@ static const VMStateDescription mps2_fpgaio_vmstate = { static Property mps2_fpgaio_properties[] = { /* Frequency of the prescale counter */ DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000), + /* Number of LEDs controlled by LED0 register */ + DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2), + DEFINE_PROP_BOOL("has-switches", MPS2FPGAIO, has_switches, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c index ce1dfe9356..140a4b9ceb 100644 --- a/hw/misc/mps2-scc.c +++ b/hw/misc/mps2-scc.c @@ -13,7 +13,7 @@ * found in the FPGA images of MPS2 development boards. * * Documentation of it can be found in the MPS2 TRM: - * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100112_0100_03_en/index.html + * https://developer.arm.com/documentation/100112/latest/ * and also in the Application Notes documenting individual FPGA images. */ @@ -31,8 +31,11 @@ REG32(CFG0, 0) REG32(CFG1, 4) +REG32(CFG2, 8) REG32(CFG3, 0xc) REG32(CFG4, 0x10) +REG32(CFG5, 0x14) +REG32(CFG6, 0x18) REG32(CFGDATA_RTN, 0xa0) REG32(CFGDATA_OUT, 0xa4) REG32(CFGCTRL, 0xa8) @@ -49,6 +52,12 @@ REG32(DLL, 0x100) REG32(AID, 0xFF8) REG32(ID, 0xFFC) +static int scc_partno(MPS2SCC *s) +{ + /* Return the partno field of the SCC_ID (0x524, 0x511, etc) */ + return extract32(s->id, 4, 8); +} + /* Handle a write via the SYS_CFG channel to the specified function/device. * Return false on error (reported to guest via SYS_CFGCTRL ERROR bit). */ @@ -57,7 +66,7 @@ static bool scc_cfg_write(MPS2SCC *s, unsigned function, { trace_mps2_scc_cfg_write(function, device, value); - if (function != 1 || device >= NUM_OSCCLK) { + if (function != 1 || device >= s->num_oscclk) { qemu_log_mask(LOG_GUEST_ERROR, "MPS2 SCC config write: bad function %d device %d\n", function, device); @@ -75,7 +84,7 @@ static bool scc_cfg_write(MPS2SCC *s, unsigned function, static bool scc_cfg_read(MPS2SCC *s, unsigned function, unsigned device, uint32_t *value) { - if (function != 1 || device >= NUM_OSCCLK) { + if (function != 1 || device >= s->num_oscclk) { qemu_log_mask(LOG_GUEST_ERROR, "MPS2 SCC config read: bad function %d device %d\n", function, device); @@ -100,7 +109,18 @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size) case A_CFG1: r = s->cfg1; break; + case A_CFG2: + if (scc_partno(s) != 0x524) { + /* CFG2 reserved on other boards */ + goto bad_offset; + } + r = s->cfg2; + break; case A_CFG3: + if (scc_partno(s) == 0x524) { + /* CFG3 reserved on AN524 */ + goto bad_offset; + } /* These are user-settable DIP switches on the board. We don't * model that, so just return zeroes. */ @@ -109,6 +129,20 @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size) case A_CFG4: r = s->cfg4; break; + case A_CFG5: + if (scc_partno(s) != 0x524) { + /* CFG5 reserved on other boards */ + goto bad_offset; + } + r = s->cfg5; + break; + case A_CFG6: + if (scc_partno(s) != 0x524) { + /* CFG6 reserved on other boards */ + goto bad_offset; + } + r = s->cfg6; + break; case A_CFGDATA_RTN: r = s->cfgdata_rtn; break; @@ -131,6 +165,7 @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size) r = s->id; break; default: + bad_offset: qemu_log_mask(LOG_GUEST_ERROR, "MPS2 SCC read: bad offset %x\n", (int) offset); r = 0; @@ -159,6 +194,30 @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value, led_set_state(s->led[i], extract32(value, i, 1)); } break; + case A_CFG2: + if (scc_partno(s) != 0x524) { + /* CFG2 reserved on other boards */ + goto bad_offset; + } + /* AN524: QSPI Select signal */ + s->cfg2 = value; + break; + case A_CFG5: + if (scc_partno(s) != 0x524) { + /* CFG5 reserved on other boards */ + goto bad_offset; + } + /* AN524: ACLK frequency in Hz */ + s->cfg5 = value; + break; + case A_CFG6: + if (scc_partno(s) != 0x524) { + /* CFG6 reserved on other boards */ + goto bad_offset; + } + /* AN524: Clock divider for BRAM */ + s->cfg6 = value; + break; case A_CFGDATA_OUT: s->cfgdata_out = value; break; @@ -202,6 +261,7 @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value, s->dll = deposit32(s->dll, 24, 8, extract32(value, 24, 8)); break; default: + bad_offset: qemu_log_mask(LOG_GUEST_ERROR, "MPS2 SCC write: bad offset 0x%x\n", (int) offset); break; @@ -222,12 +282,15 @@ static void mps2_scc_reset(DeviceState *dev) trace_mps2_scc_reset(); s->cfg0 = 0; s->cfg1 = 0; + s->cfg2 = 0; + s->cfg5 = 0; + s->cfg6 = 0; s->cfgdata_rtn = 0; s->cfgdata_out = 0; s->cfgctrl = 0x100000; s->cfgstat = 0; s->dll = 0xffff0001; - for (i = 0; i < NUM_OSCCLK; i++) { + for (i = 0; i < s->num_oscclk; i++) { s->oscclk[i] = s->oscclk_reset[i]; } for (i = 0; i < ARRAY_SIZE(s->led); i++) { @@ -254,21 +317,28 @@ static void mps2_scc_realize(DeviceState *dev, Error **errp) LED_COLOR_GREEN, name); g_free(name); } + + s->oscclk = g_new0(uint32_t, s->num_oscclk); } static const VMStateDescription mps2_scc_vmstate = { .name = "mps2-scc", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 3, + .minimum_version_id = 3, .fields = (VMStateField[]) { VMSTATE_UINT32(cfg0, MPS2SCC), VMSTATE_UINT32(cfg1, MPS2SCC), + VMSTATE_UINT32(cfg2, MPS2SCC), + /* cfg3, cfg4 are read-only so need not be migrated */ + VMSTATE_UINT32(cfg5, MPS2SCC), + VMSTATE_UINT32(cfg6, MPS2SCC), VMSTATE_UINT32(cfgdata_rtn, MPS2SCC), VMSTATE_UINT32(cfgdata_out, MPS2SCC), VMSTATE_UINT32(cfgctrl, MPS2SCC), VMSTATE_UINT32(cfgstat, MPS2SCC), VMSTATE_UINT32(dll, MPS2SCC), - VMSTATE_UINT32_ARRAY(oscclk, MPS2SCC, NUM_OSCCLK), + VMSTATE_VARRAY_UINT32(oscclk, MPS2SCC, num_oscclk, + 0, vmstate_info_uint32, uint32_t), VMSTATE_END_OF_LIST() } }; @@ -280,14 +350,13 @@ static Property mps2_scc_properties[] = { DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, cfg4, 0), DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0), DEFINE_PROP_UINT32("scc-id", MPS2SCC, id, 0), - /* These are the initial settings for the source clocks on the board. + /* + * These are the initial settings for the source clocks on the board. * In hardware they can be configured via a config file read by the * motherboard configuration controller to suit the FPGA image. - * These default values are used by most of the standard FPGA images. */ - DEFINE_PROP_UINT32("oscclk0", MPS2SCC, oscclk_reset[0], 50000000), - DEFINE_PROP_UINT32("oscclk1", MPS2SCC, oscclk_reset[1], 24576000), - DEFINE_PROP_UINT32("oscclk2", MPS2SCC, oscclk_reset[2], 25000000), + DEFINE_PROP_ARRAY("oscclk", MPS2SCC, num_oscclk, oscclk_reset, + qdev_prop_uint32, uint32_t), DEFINE_PROP_END_OF_LIST(), }; |