mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20210308' into staging
target-arm queue: * sbsa-ref: remove cortex-a53 from list of supported cpus * sbsa-ref: add 'max' to list of allowed cpus * target/arm: Add support for FEAT_SSBS, Speculative Store Bypass Safe * npcm7xx: add EMC model * xlnx-zynqmp: Remove obsolete 'has_rpu' property * target/arm: Speed up aarch64 TBL/TBX * virtio-mmio: improve virtio-mmio get_dev_path alog * target/arm: Use TCF0 and TFSRE0 for unprivileged tag checks * target/arm: Restrict v8M IDAU to TCG * target/arm/cpu: Update coding style to make checkpatch.pl happy * musicpal, tc6393xb, omap_lcdc, tcx: drop dead code for non-32-bit-RGB surfaces * Add new board: mps3-an524 # gpg: Signature made Mon 08 Mar 2021 11:56:24 GMT # 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-20210308: (49 commits) hw/arm/mps2: Update old infocenter.arm.com URLs docs/system/arm/mps2.rst: Document the new mps3-an524 board hw/arm/mps2-tz: Provide PL031 RTC on mps3-an524 hw/arm/mps2-tz: Stub out USB controller for mps3-an524 hw/arm/mps2-tz: Add new mps3-an524 board hw/arm/mps2-tz: Get armv7m_load_kernel() size argument from RAMInfo hw/arm/mps2-tz: Support ROMs as well as RAMs hw/arm/mps2-tz: Set MachineClass default_ram info from RAMInfo data hw/arm/mps2-tz: Make RAM arrangement board-specific hw/arm/mps2-tz: Allow boards to have different PPCInfo data hw/arm/mps2-tz: Size the uart-irq-orgate based on the number of UARTs hw/arm/mps2-tz: Move device IRQ info to data structures hw/arm/mps2-tz: Allow PPCPortInfo structures to specify device interrupts hw/arm/mps2-tz: Correct wrong interrupt numbers for DMA and SPI hw/misc/mps2-scc: Implement CFG_REG5 and CFG_REG6 for MPS3 AN524 hw/arm/mps2-tz: Make number of IRQs board-specific hw/arm/mps2-tz: Condition IRQ splitting on number of CPUs, not board type hw/arm/mps2-tz: Make FPGAIO switch and LED config per-board hw/misc/mps2-fpgaio: Support SWITCH register hw/misc/mps2-fpgaio: Make number of LEDs configurable by board ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
|
||||
================================================================================================================
|
||||
Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``)
|
||||
=========================================================================================================================================
|
||||
|
||||
These board models all use Arm M-profile CPUs.
|
||||
|
||||
The Arm MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
|
||||
FPGA but is otherwise the same as the 2). Since the CPU itself
|
||||
and most of the devices are in the FPGA, the details of the board
|
||||
as seen by the guest depend significantly on the FPGA image.
|
||||
The Arm MPS2, MPS2+ and MPS3 dev boards are FPGA based (the 2+ has a
|
||||
bigger FPGA but is otherwise the same as the 2; the 3 has a bigger
|
||||
FPGA again, can handle 4GB of RAM and has a USB controller and QSPI flash).
|
||||
|
||||
Since the CPU itself and most of the devices are in the FPGA, the
|
||||
details of the board as seen by the guest depend significantly on the
|
||||
FPGA image.
|
||||
|
||||
QEMU models the following FPGA images:
|
||||
|
||||
@@ -22,12 +25,21 @@ QEMU models the following FPGA images:
|
||||
Cortex-M3 'DesignStart' as documented in Arm Application Note AN511
|
||||
``mps2-an521``
|
||||
Dual Cortex-M33 as documented in Arm Application Note AN521
|
||||
``mps3-an524``
|
||||
Dual Cortex-M33 on an MPS3, as documented in Arm Application Note AN524
|
||||
|
||||
Differences between QEMU and real hardware:
|
||||
|
||||
- AN385/AN386 remapping of low 16K of memory to either ZBT SSRAM1 or to
|
||||
block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as
|
||||
if zbt_boot_ctrl is always zero)
|
||||
- AN524 remapping of low memory to either BRAM or to QSPI flash is
|
||||
unimplemented (QEMU always maps this to BRAM, ignoring the
|
||||
SCC CFG_REG0 memory-remap bit)
|
||||
- QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest
|
||||
visible difference is that the LAN9118 doesn't support checksum
|
||||
offloading
|
||||
- QEMU does not model the QSPI flash in MPS3 boards as real QSPI
|
||||
flash, but only as simple ROM, so attempting to rewrite the flash
|
||||
from the guest will fail
|
||||
- QEMU does not model the USB controller in MPS3 boards
|
||||
|
||||
@@ -44,6 +44,7 @@ Supported devices
|
||||
* Analog to Digital Converter (ADC)
|
||||
* Pulse Width Modulation (PWM)
|
||||
* SMBus controller (SMBF)
|
||||
* Ethernet controller (EMC)
|
||||
|
||||
Missing devices
|
||||
---------------
|
||||
@@ -57,7 +58,7 @@ Missing devices
|
||||
* Shared memory (SHM)
|
||||
* eSPI slave interface
|
||||
|
||||
* Ethernet controllers (GMAC and EMC)
|
||||
* Ethernet controller (GMAC)
|
||||
* USB device (USBD)
|
||||
* Peripheral SPI controller (PSPI)
|
||||
* SD/MMC host
|
||||
|
||||
+529
-113
File diff suppressed because it is too large
Load Diff
@@ -373,6 +373,11 @@ static void mps2_common_init(MachineState *machine)
|
||||
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
|
||||
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
|
||||
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
|
||||
/* All these FPGA images have the same OSCCLK configuration */
|
||||
qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
|
||||
qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
|
||||
qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
|
||||
qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
|
||||
sysbus_realize(SYS_BUS_DEVICE(&mms->scc), &error_fatal);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000);
|
||||
object_initialize_child(OBJECT(mms), "fpgaio",
|
||||
|
||||
+24
-40
@@ -512,53 +512,37 @@ static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
|
||||
}
|
||||
}
|
||||
|
||||
#define SET_LCD_PIXEL(depth, type) \
|
||||
static inline void glue(set_lcd_pixel, depth) \
|
||||
(musicpal_lcd_state *s, int x, int y, type col) \
|
||||
{ \
|
||||
int dx, dy; \
|
||||
DisplaySurface *surface = qemu_console_surface(s->con); \
|
||||
type *pixel = &((type *) surface_data(surface))[(y * 128 * 3 + x) * 3]; \
|
||||
\
|
||||
for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
|
||||
for (dx = 0; dx < 3; dx++, pixel++) \
|
||||
*pixel = col; \
|
||||
static inline void set_lcd_pixel32(musicpal_lcd_state *s,
|
||||
int x, int y, uint32_t col)
|
||||
{
|
||||
int dx, dy;
|
||||
DisplaySurface *surface = qemu_console_surface(s->con);
|
||||
uint32_t *pixel =
|
||||
&((uint32_t *) surface_data(surface))[(y * 128 * 3 + x) * 3];
|
||||
|
||||
for (dy = 0; dy < 3; dy++, pixel += 127 * 3) {
|
||||
for (dx = 0; dx < 3; dx++, pixel++) {
|
||||
*pixel = col;
|
||||
}
|
||||
}
|
||||
}
|
||||
SET_LCD_PIXEL(8, uint8_t)
|
||||
SET_LCD_PIXEL(16, uint16_t)
|
||||
SET_LCD_PIXEL(32, uint32_t)
|
||||
|
||||
static void lcd_refresh(void *opaque)
|
||||
{
|
||||
musicpal_lcd_state *s = opaque;
|
||||
DisplaySurface *surface = qemu_console_surface(s->con);
|
||||
int x, y, col;
|
||||
|
||||
switch (surface_bits_per_pixel(surface)) {
|
||||
case 0:
|
||||
return;
|
||||
#define LCD_REFRESH(depth, func) \
|
||||
case depth: \
|
||||
col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
|
||||
scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
|
||||
scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
|
||||
for (x = 0; x < 128; x++) { \
|
||||
for (y = 0; y < 64; y++) { \
|
||||
if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
|
||||
glue(set_lcd_pixel, depth)(s, x, y, col); \
|
||||
} else { \
|
||||
glue(set_lcd_pixel, depth)(s, x, y, 0); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
break;
|
||||
LCD_REFRESH(8, rgb_to_pixel8)
|
||||
LCD_REFRESH(16, rgb_to_pixel16)
|
||||
LCD_REFRESH(32, (is_surface_bgr(surface) ?
|
||||
rgb_to_pixel32bgr : rgb_to_pixel32))
|
||||
default:
|
||||
hw_error("unsupported colour depth %i\n",
|
||||
surface_bits_per_pixel(surface));
|
||||
col = rgb_to_pixel32(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff),
|
||||
scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff),
|
||||
scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff));
|
||||
for (x = 0; x < 128; x++) {
|
||||
for (y = 0; y < 64; y++) {
|
||||
if (s->video_ram[x + (y / 8) * 128] & (1 << (y % 8))) {
|
||||
set_lcd_pixel32(s, x, y, col);
|
||||
} else {
|
||||
set_lcd_pixel32(s, x, y, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
|
||||
|
||||
+48
-2
@@ -82,6 +82,8 @@ enum NPCM7xxInterrupt {
|
||||
NPCM7XX_UART1_IRQ,
|
||||
NPCM7XX_UART2_IRQ,
|
||||
NPCM7XX_UART3_IRQ,
|
||||
NPCM7XX_EMC1RX_IRQ = 15,
|
||||
NPCM7XX_EMC1TX_IRQ,
|
||||
NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
|
||||
NPCM7XX_TIMER1_IRQ,
|
||||
NPCM7XX_TIMER2_IRQ,
|
||||
@@ -120,6 +122,8 @@ enum NPCM7xxInterrupt {
|
||||
NPCM7XX_SMBUS15_IRQ,
|
||||
NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
|
||||
NPCM7XX_PWM1_IRQ, /* PWM module 1 */
|
||||
NPCM7XX_EMC2RX_IRQ = 114,
|
||||
NPCM7XX_EMC2TX_IRQ,
|
||||
NPCM7XX_GPIO0_IRQ = 116,
|
||||
NPCM7XX_GPIO1_IRQ,
|
||||
NPCM7XX_GPIO2_IRQ,
|
||||
@@ -188,6 +192,12 @@ static const hwaddr npcm7xx_smbus_addr[] = {
|
||||
0xf008f000,
|
||||
};
|
||||
|
||||
/* Register base address for each EMC Module */
|
||||
static const hwaddr npcm7xx_emc_addr[] = {
|
||||
0xf0825000,
|
||||
0xf0826000,
|
||||
};
|
||||
|
||||
static const struct {
|
||||
hwaddr regs_addr;
|
||||
uint32_t unconnected_pins;
|
||||
@@ -406,6 +416,10 @@ static void npcm7xx_init(Object *obj)
|
||||
for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
|
||||
object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
|
||||
object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
|
||||
}
|
||||
}
|
||||
|
||||
static void npcm7xx_realize(DeviceState *dev, Error **errp)
|
||||
@@ -589,6 +603,40 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
|
||||
sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
|
||||
}
|
||||
|
||||
/*
|
||||
* EMC Modules. Cannot fail.
|
||||
* The mapping of the device to its netdev backend works as follows:
|
||||
* emc[i] = nd_table[i]
|
||||
* This works around the inability to specify the netdev property for the
|
||||
* emc device: it's not pluggable and thus the -device option can't be
|
||||
* used.
|
||||
*/
|
||||
QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_emc_addr) != ARRAY_SIZE(s->emc));
|
||||
QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->emc) != 2);
|
||||
for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
|
||||
s->emc[i].emc_num = i;
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(&s->emc[i]);
|
||||
if (nd_table[i].used) {
|
||||
qemu_check_nic_model(&nd_table[i], TYPE_NPCM7XX_EMC);
|
||||
qdev_set_nic_properties(DEVICE(sbd), &nd_table[i]);
|
||||
}
|
||||
/*
|
||||
* The device exists regardless of whether it's connected to a QEMU
|
||||
* netdev backend. So always instantiate it even if there is no
|
||||
* backend.
|
||||
*/
|
||||
sysbus_realize(sbd, &error_abort);
|
||||
sysbus_mmio_map(sbd, 0, npcm7xx_emc_addr[i]);
|
||||
int tx_irq = i == 0 ? NPCM7XX_EMC1TX_IRQ : NPCM7XX_EMC2TX_IRQ;
|
||||
int rx_irq = i == 0 ? NPCM7XX_EMC1RX_IRQ : NPCM7XX_EMC2RX_IRQ;
|
||||
/*
|
||||
* N.B. The values for the second argument sysbus_connect_irq are
|
||||
* chosen to match the registration order in npcm7xx_emc_realize.
|
||||
*/
|
||||
sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, tx_irq));
|
||||
sysbus_connect_irq(sbd, 1, npcm7xx_irq(s, rx_irq));
|
||||
}
|
||||
|
||||
/*
|
||||
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
|
||||
* specified, but this is a programming error.
|
||||
@@ -649,8 +697,6 @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
|
||||
create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
|
||||
create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
|
||||
create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
|
||||
create_unimplemented_device("npcm7xx.emc1", 0xf0825000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.emc2", 0xf0826000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.usbd[0]", 0xf0830000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.usbd[1]", 0xf0831000, 4 * KiB);
|
||||
create_unimplemented_device("npcm7xx.usbd[2]", 0xf0832000, 4 * KiB);
|
||||
|
||||
+1
-1
@@ -145,9 +145,9 @@ static const int sbsa_ref_irqmap[] = {
|
||||
};
|
||||
|
||||
static const char * const valid_cpus[] = {
|
||||
ARM_CPU_TYPE_NAME("cortex-a53"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a57"),
|
||||
ARM_CPU_TYPE_NAME("cortex-a72"),
|
||||
ARM_CPU_TYPE_NAME("max"),
|
||||
};
|
||||
|
||||
static bool cpu_type_valid(const char *cpu)
|
||||
|
||||
@@ -443,11 +443,6 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
if (s->has_rpu) {
|
||||
info_report("The 'has_rpu' property is no longer required, to use the "
|
||||
"RPUs just use -smp 6.");
|
||||
}
|
||||
|
||||
xlnx_zynqmp_create_rpu(ms, s, boot_cpu, &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
@@ -646,7 +641,6 @@ static Property xlnx_zynqmp_props[] = {
|
||||
DEFINE_PROP_STRING("boot-cpu", XlnxZynqMPState, boot_cpu),
|
||||
DEFINE_PROP_BOOL("secure", XlnxZynqMPState, secure, false),
|
||||
DEFINE_PROP_BOOL("virtualization", XlnxZynqMPState, virt, false),
|
||||
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
|
||||
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
|
||||
MemoryRegion *),
|
||||
DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* QEMU OMAP LCD Emulator templates
|
||||
*
|
||||
* Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
||||
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if DEPTH == 32
|
||||
# define BPP 4
|
||||
# define PIXEL_TYPE uint32_t
|
||||
#else
|
||||
# error unsupport depth
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 2-bit colour
|
||||
*/
|
||||
static void glue(draw_line2_, DEPTH)(void *opaque,
|
||||
uint8_t *d, const uint8_t *s, int width, int deststep)
|
||||
{
|
||||
uint16_t *pal = opaque;
|
||||
uint8_t v, r, g, b;
|
||||
|
||||
do {
|
||||
v = ldub_p((void *) s);
|
||||
r = (pal[v & 3] >> 4) & 0xf0;
|
||||
g = pal[v & 3] & 0xf0;
|
||||
b = (pal[v & 3] << 4) & 0xf0;
|
||||
((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
|
||||
d += BPP;
|
||||
v >>= 2;
|
||||
r = (pal[v & 3] >> 4) & 0xf0;
|
||||
g = pal[v & 3] & 0xf0;
|
||||
b = (pal[v & 3] << 4) & 0xf0;
|
||||
((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
|
||||
d += BPP;
|
||||
v >>= 2;
|
||||
r = (pal[v & 3] >> 4) & 0xf0;
|
||||
g = pal[v & 3] & 0xf0;
|
||||
b = (pal[v & 3] << 4) & 0xf0;
|
||||
((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
|
||||
d += BPP;
|
||||
v >>= 2;
|
||||
r = (pal[v & 3] >> 4) & 0xf0;
|
||||
g = pal[v & 3] & 0xf0;
|
||||
b = (pal[v & 3] << 4) & 0xf0;
|
||||
((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
|
||||
d += BPP;
|
||||
s ++;
|
||||
width -= 4;
|
||||
} while (width > 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 4-bit colour
|
||||
*/
|
||||
static void glue(draw_line4_, DEPTH)(void *opaque,
|
||||
uint8_t *d, const uint8_t *s, int width, int deststep)
|
||||
{
|
||||
uint16_t *pal = opaque;
|
||||
uint8_t v, r, g, b;
|
||||
|
||||
do {
|
||||
v = ldub_p((void *) s);
|
||||
r = (pal[v & 0xf] >> 4) & 0xf0;
|
||||
g = pal[v & 0xf] & 0xf0;
|
||||
b = (pal[v & 0xf] << 4) & 0xf0;
|
||||
((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
|
||||
d += BPP;
|
||||
v >>= 4;
|
||||
r = (pal[v & 0xf] >> 4) & 0xf0;
|
||||
g = pal[v & 0xf] & 0xf0;
|
||||
b = (pal[v & 0xf] << 4) & 0xf0;
|
||||
((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
|
||||
d += BPP;
|
||||
s ++;
|
||||
width -= 2;
|
||||
} while (width > 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 8-bit colour
|
||||
*/
|
||||
static void glue(draw_line8_, DEPTH)(void *opaque,
|
||||
uint8_t *d, const uint8_t *s, int width, int deststep)
|
||||
{
|
||||
uint16_t *pal = opaque;
|
||||
uint8_t v, r, g, b;
|
||||
|
||||
do {
|
||||
v = ldub_p((void *) s);
|
||||
r = (pal[v] >> 4) & 0xf0;
|
||||
g = pal[v] & 0xf0;
|
||||
b = (pal[v] << 4) & 0xf0;
|
||||
((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
|
||||
s ++;
|
||||
d += BPP;
|
||||
} while (-- width != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 12-bit colour
|
||||
*/
|
||||
static void glue(draw_line12_, DEPTH)(void *opaque,
|
||||
uint8_t *d, const uint8_t *s, int width, int deststep)
|
||||
{
|
||||
uint16_t v;
|
||||
uint8_t r, g, b;
|
||||
|
||||
do {
|
||||
v = lduw_le_p((void *) s);
|
||||
r = (v >> 4) & 0xf0;
|
||||
g = v & 0xf0;
|
||||
b = (v << 4) & 0xf0;
|
||||
((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
|
||||
s += 2;
|
||||
d += BPP;
|
||||
} while (-- width != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 16-bit colour
|
||||
*/
|
||||
static void glue(draw_line16_, DEPTH)(void *opaque,
|
||||
uint8_t *d, const uint8_t *s, int width, int deststep)
|
||||
{
|
||||
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
|
||||
memcpy(d, s, width * 2);
|
||||
#else
|
||||
uint16_t v;
|
||||
uint8_t r, g, b;
|
||||
|
||||
do {
|
||||
v = lduw_le_p((void *) s);
|
||||
r = (v >> 8) & 0xf8;
|
||||
g = (v >> 3) & 0xfc;
|
||||
b = (v << 3) & 0xf8;
|
||||
((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
|
||||
s += 2;
|
||||
d += BPP;
|
||||
} while (-- width != 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef DEPTH
|
||||
#undef BPP
|
||||
#undef PIXEL_TYPE
|
||||
+125
-4
@@ -70,16 +70,137 @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
|
||||
qemu_irq_lower(s->irq);
|
||||
}
|
||||
|
||||
#define draw_line_func drawfn
|
||||
/*
|
||||
* 2-bit colour
|
||||
*/
|
||||
static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
|
||||
int width, int deststep)
|
||||
{
|
||||
uint16_t *pal = opaque;
|
||||
uint8_t v, r, g, b;
|
||||
|
||||
#define DEPTH 32
|
||||
#include "omap_lcd_template.h"
|
||||
do {
|
||||
v = ldub_p((void *) s);
|
||||
r = (pal[v & 3] >> 4) & 0xf0;
|
||||
g = pal[v & 3] & 0xf0;
|
||||
b = (pal[v & 3] << 4) & 0xf0;
|
||||
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
|
||||
d += 4;
|
||||
v >>= 2;
|
||||
r = (pal[v & 3] >> 4) & 0xf0;
|
||||
g = pal[v & 3] & 0xf0;
|
||||
b = (pal[v & 3] << 4) & 0xf0;
|
||||
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
|
||||
d += 4;
|
||||
v >>= 2;
|
||||
r = (pal[v & 3] >> 4) & 0xf0;
|
||||
g = pal[v & 3] & 0xf0;
|
||||
b = (pal[v & 3] << 4) & 0xf0;
|
||||
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
|
||||
d += 4;
|
||||
v >>= 2;
|
||||
r = (pal[v & 3] >> 4) & 0xf0;
|
||||
g = pal[v & 3] & 0xf0;
|
||||
b = (pal[v & 3] << 4) & 0xf0;
|
||||
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
|
||||
d += 4;
|
||||
s++;
|
||||
width -= 4;
|
||||
} while (width > 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 4-bit colour
|
||||
*/
|
||||
static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
|
||||
int width, int deststep)
|
||||
{
|
||||
uint16_t *pal = opaque;
|
||||
uint8_t v, r, g, b;
|
||||
|
||||
do {
|
||||
v = ldub_p((void *) s);
|
||||
r = (pal[v & 0xf] >> 4) & 0xf0;
|
||||
g = pal[v & 0xf] & 0xf0;
|
||||
b = (pal[v & 0xf] << 4) & 0xf0;
|
||||
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
|
||||
d += 4;
|
||||
v >>= 4;
|
||||
r = (pal[v & 0xf] >> 4) & 0xf0;
|
||||
g = pal[v & 0xf] & 0xf0;
|
||||
b = (pal[v & 0xf] << 4) & 0xf0;
|
||||
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
|
||||
d += 4;
|
||||
s++;
|
||||
width -= 2;
|
||||
} while (width > 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 8-bit colour
|
||||
*/
|
||||
static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
|
||||
int width, int deststep)
|
||||
{
|
||||
uint16_t *pal = opaque;
|
||||
uint8_t v, r, g, b;
|
||||
|
||||
do {
|
||||
v = ldub_p((void *) s);
|
||||
r = (pal[v] >> 4) & 0xf0;
|
||||
g = pal[v] & 0xf0;
|
||||
b = (pal[v] << 4) & 0xf0;
|
||||
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
|
||||
s++;
|
||||
d += 4;
|
||||
} while (-- width != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 12-bit colour
|
||||
*/
|
||||
static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
|
||||
int width, int deststep)
|
||||
{
|
||||
uint16_t v;
|
||||
uint8_t r, g, b;
|
||||
|
||||
do {
|
||||
v = lduw_le_p((void *) s);
|
||||
r = (v >> 4) & 0xf0;
|
||||
g = v & 0xf0;
|
||||
b = (v << 4) & 0xf0;
|
||||
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
|
||||
s += 2;
|
||||
d += 4;
|
||||
} while (-- width != 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* 16-bit colour
|
||||
*/
|
||||
static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
|
||||
int width, int deststep)
|
||||
{
|
||||
uint16_t v;
|
||||
uint8_t r, g, b;
|
||||
|
||||
do {
|
||||
v = lduw_le_p((void *) s);
|
||||
r = (v >> 8) & 0xf8;
|
||||
g = (v >> 3) & 0xfc;
|
||||
b = (v << 3) & 0xf8;
|
||||
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
|
||||
s += 2;
|
||||
d += 4;
|
||||
} while (-- width != 0);
|
||||
}
|
||||
|
||||
static void omap_update_display(void *opaque)
|
||||
{
|
||||
struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque;
|
||||
DisplaySurface *surface;
|
||||
draw_line_func draw_line;
|
||||
drawfn draw_line;
|
||||
int size, height, first, last;
|
||||
int width, linesize, step, bpp, frame_offset;
|
||||
hwaddr frame_base;
|
||||
|
||||
+16
-32
@@ -410,43 +410,27 @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
|
||||
(uint32_t) addr, value & 0xff);
|
||||
}
|
||||
|
||||
#define BITS 8
|
||||
#include "tc6393xb_template.h"
|
||||
#define BITS 15
|
||||
#include "tc6393xb_template.h"
|
||||
#define BITS 16
|
||||
#include "tc6393xb_template.h"
|
||||
#define BITS 24
|
||||
#include "tc6393xb_template.h"
|
||||
#define BITS 32
|
||||
#include "tc6393xb_template.h"
|
||||
|
||||
static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
|
||||
{
|
||||
DisplaySurface *surface = qemu_console_surface(s->con);
|
||||
int i;
|
||||
uint16_t *data_buffer;
|
||||
uint8_t *data_display;
|
||||
|
||||
switch (surface_bits_per_pixel(surface)) {
|
||||
case 8:
|
||||
tc6393xb_draw_graphic8(s);
|
||||
break;
|
||||
case 15:
|
||||
tc6393xb_draw_graphic15(s);
|
||||
break;
|
||||
case 16:
|
||||
tc6393xb_draw_graphic16(s);
|
||||
break;
|
||||
case 24:
|
||||
tc6393xb_draw_graphic24(s);
|
||||
break;
|
||||
case 32:
|
||||
tc6393xb_draw_graphic32(s);
|
||||
break;
|
||||
default:
|
||||
printf("tc6393xb: unknown depth %d\n",
|
||||
surface_bits_per_pixel(surface));
|
||||
return;
|
||||
data_buffer = s->vram_ptr;
|
||||
data_display = surface_data(surface);
|
||||
for (i = 0; i < s->scr_height; i++) {
|
||||
int j;
|
||||
for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
|
||||
uint16_t color = *data_buffer;
|
||||
uint32_t dest_color = rgb_to_pixel32(
|
||||
((color & 0xf800) * 0x108) >> 11,
|
||||
((color & 0x7e0) * 0x41) >> 9,
|
||||
((color & 0x1f) * 0x21) >> 2
|
||||
);
|
||||
*(uint32_t *)data_display = dest_color;
|
||||
}
|
||||
}
|
||||
|
||||
dpy_gfx_update_full(s->con);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Toshiba TC6393XB I/O Controller.
|
||||
* Found in Sharp Zaurus SL-6000 (tosa) or some
|
||||
* Toshiba e-Series PDAs.
|
||||
*
|
||||
* FB support code. Based on G364 fb emulator
|
||||
*
|
||||
* Copyright (c) 2007 Hervé Poussineau
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if BITS == 8
|
||||
# define SET_PIXEL(addr, color) (*(uint8_t *)addr = color)
|
||||
#elif BITS == 15 || BITS == 16
|
||||
# define SET_PIXEL(addr, color) (*(uint16_t *)addr = color)
|
||||
#elif BITS == 24
|
||||
# define SET_PIXEL(addr, color) \
|
||||
do { \
|
||||
addr[0] = color; \
|
||||
addr[1] = (color) >> 8; \
|
||||
addr[2] = (color) >> 16; \
|
||||
} while (0)
|
||||
#elif BITS == 32
|
||||
# define SET_PIXEL(addr, color) (*(uint32_t *)addr = color)
|
||||
#else
|
||||
# error unknown bit depth
|
||||
#endif
|
||||
|
||||
|
||||
static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s)
|
||||
{
|
||||
DisplaySurface *surface = qemu_console_surface(s->con);
|
||||
int i;
|
||||
uint16_t *data_buffer;
|
||||
uint8_t *data_display;
|
||||
|
||||
data_buffer = s->vram_ptr;
|
||||
data_display = surface_data(surface);
|
||||
for(i = 0; i < s->scr_height; i++) {
|
||||
#if (BITS == 16)
|
||||
memcpy(data_display, data_buffer, s->scr_width * 2);
|
||||
data_buffer += s->scr_width;
|
||||
data_display += surface_stride(surface);
|
||||
#else
|
||||
int j;
|
||||
for (j = 0; j < s->scr_width; j++, data_display += BITS / 8, data_buffer++) {
|
||||
uint16_t color = *data_buffer;
|
||||
uint32_t dest_color = glue(rgb_to_pixel, BITS)(
|
||||
((color & 0xf800) * 0x108) >> 11,
|
||||
((color & 0x7e0) * 0x41) >> 9,
|
||||
((color & 0x1f) * 0x21) >> 2
|
||||
);
|
||||
SET_PIXEL(data_display, dest_color);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#undef BITS
|
||||
#undef SET_PIXEL
|
||||
+8
-23
@@ -128,15 +128,10 @@ static int tcx_check_dirty(TCXState *s, DirtyBitmapSnapshot *snap,
|
||||
|
||||
static void update_palette_entries(TCXState *s, int start, int end)
|
||||
{
|
||||
DisplaySurface *surface = qemu_console_surface(s->con);
|
||||
int i;
|
||||
|
||||
for (i = start; i < end; i++) {
|
||||
if (is_surface_bgr(surface)) {
|
||||
s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
|
||||
} else {
|
||||
s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
|
||||
}
|
||||
s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
|
||||
}
|
||||
tcx_set_dirty(s, 0, memory_region_size(&s->vram_mem));
|
||||
}
|
||||
@@ -181,21 +176,18 @@ static void tcx_draw_cursor32(TCXState *s1, uint8_t *d,
|
||||
}
|
||||
|
||||
/*
|
||||
XXX Could be much more optimal:
|
||||
* detect if line/page/whole screen is in 24 bit mode
|
||||
* if destination is also BGR, use memcpy
|
||||
*/
|
||||
* XXX Could be much more optimal:
|
||||
* detect if line/page/whole screen is in 24 bit mode
|
||||
*/
|
||||
static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
|
||||
const uint8_t *s, int width,
|
||||
const uint32_t *cplane,
|
||||
const uint32_t *s24)
|
||||
{
|
||||
DisplaySurface *surface = qemu_console_surface(s1->con);
|
||||
int x, bgr, r, g, b;
|
||||
int x, r, g, b;
|
||||
uint8_t val, *p8;
|
||||
uint32_t *p = (uint32_t *)d;
|
||||
uint32_t dval;
|
||||
bgr = is_surface_bgr(surface);
|
||||
for(x = 0; x < width; x++, s++, s24++) {
|
||||
if (be32_to_cpu(*cplane) & 0x03000000) {
|
||||
/* 24-bit direct, BGR order */
|
||||
@@ -204,10 +196,7 @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
|
||||
b = *p8++;
|
||||
g = *p8++;
|
||||
r = *p8;
|
||||
if (bgr)
|
||||
dval = rgb_to_pixel32bgr(r, g, b);
|
||||
else
|
||||
dval = rgb_to_pixel32(r, g, b);
|
||||
dval = rgb_to_pixel32(r, g, b);
|
||||
} else {
|
||||
/* 8-bit pseudocolor */
|
||||
val = *s;
|
||||
@@ -230,9 +219,7 @@ static void tcx_update_display(void *opaque)
|
||||
int y, y_start, dd, ds;
|
||||
uint8_t *d, *s;
|
||||
|
||||
if (surface_bits_per_pixel(surface) != 32) {
|
||||
return;
|
||||
}
|
||||
assert(surface_bits_per_pixel(surface) == 32);
|
||||
|
||||
page = 0;
|
||||
y_start = -1;
|
||||
@@ -283,9 +270,7 @@ static void tcx24_update_display(void *opaque)
|
||||
uint8_t *d, *s;
|
||||
uint32_t *cptr, *s24;
|
||||
|
||||
if (surface_bits_per_pixel(surface) != 32) {
|
||||
return;
|
||||
}
|
||||
assert(surface_bits_per_pixel(surface) == 32);
|
||||
|
||||
page = 0;
|
||||
y_start = -1;
|
||||
|
||||
@@ -1040,7 +1040,6 @@ static void npcm7xx_smbus_init(Object *obj)
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
|
||||
s->bus = i2c_init_bus(DEVICE(s), "i2c-bus");
|
||||
s->status = NPCM7XX_SMBUS_STATUS_IDLE;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_npcm7xx_smbus = {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
+34
-9
@@ -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(),
|
||||
};
|
||||
|
||||
|
||||
+81
-12
@@ -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(),
|
||||
};
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user