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-20150813' into staging
target-arm queue: * i.MX code cleanup/refactorings * i.MX UART fix to work with uninitialized chardev * minor GIC code refactorings * implement the ARM Secure physical timer * implement the ARM Hypervisor timer # gpg: Signature made Thu 13 Aug 2015 11:40:56 BST using RSA key ID 14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" * remotes/pmaydell/tags/pull-target-arm-20150813: (27 commits) i.MX: Fix UART driver to work with unitialized "chardev" device hw/cpu/a15mpcore: Wire up hyp and secure physical timer interrupts hw/arm/virt: Wire up secure timer interrupt target-arm: Add AArch32 banked register access to secure physical timer target-arm: Add the AArch64 view of the Secure physical timer target-arm: Add debug check for mismatched cpreg resets Introduce gic_class_name() instead of repeating condition hw/arm/gic: Kill code duplication Merge memory_region_init_reservation() into memory_region_init_io() i.MX: Fix Coding style for GPT emulator i.MX: Split GPT emulator in a header file and a source file i.MX: Fix Coding style for EPIT emulator i.MX: Split EPIT emulator in a header file and a source file i.MX: Fix Coding style for CCM emulator i.MX: Split CCM emulator in a header file and a source file i.MX: Fix Coding style for AVIC emulator. i.MX: Split AVIC emulator in a header file and a source file i.MX:Fix Coding style for UART emulator. i.MX: Move serial initialization to init/realize of DeviceClass. i.MX: Split UART emulator in a header file and a source file ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+3
-2
@@ -22,6 +22,7 @@
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/char/serial.h"
|
||||
#include "hw/intc/imx_avic.h"
|
||||
#include "hw/arm/imx.h"
|
||||
|
||||
/* Memory map for Kzm Emulation Baseboard:
|
||||
@@ -106,7 +107,7 @@ static void kzm_init(MachineState *machine)
|
||||
memory_region_init_ram(sram, NULL, "kzm.sram", 0x4000, &error_abort);
|
||||
memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram);
|
||||
|
||||
dev = sysbus_create_varargs("imx_avic", 0x68000000,
|
||||
dev = sysbus_create_varargs(TYPE_IMX_AVIC, 0x68000000,
|
||||
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
|
||||
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
|
||||
NULL);
|
||||
@@ -114,7 +115,7 @@ static void kzm_init(MachineState *machine)
|
||||
imx_serial_create(0, 0x43f90000, qdev_get_gpio_in(dev, 45));
|
||||
imx_serial_create(1, 0x43f94000, qdev_get_gpio_in(dev, 32));
|
||||
|
||||
ccm = sysbus_create_simple("imx_ccm", 0x53f80000, NULL);
|
||||
ccm = sysbus_create_simple(TYPE_IMX_CCM, 0x53f80000, NULL);
|
||||
|
||||
imx_timerp_create(0x53f94000, qdev_get_gpio_in(dev, 28), ccm);
|
||||
imx_timerp_create(0x53f98000, qdev_get_gpio_in(dev, 27), ccm);
|
||||
|
||||
+20
-12
@@ -48,6 +48,8 @@
|
||||
#include "hw/arm/sysbus-fdt.h"
|
||||
#include "hw/platform-bus.h"
|
||||
#include "hw/arm/fdt.h"
|
||||
#include "hw/intc/arm_gic_common.h"
|
||||
#include "kvm_arm.h"
|
||||
|
||||
/* Number of external interrupt lines to configure the GIC with */
|
||||
#define NUM_IRQS 256
|
||||
@@ -365,12 +367,10 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic)
|
||||
/* We create a standalone GIC v2 */
|
||||
DeviceState *gicdev;
|
||||
SysBusDevice *gicbusdev;
|
||||
const char *gictype = "arm_gic";
|
||||
const char *gictype;
|
||||
int i;
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
gictype = "kvm-arm-gic";
|
||||
}
|
||||
gictype = gic_class_name();
|
||||
|
||||
gicdev = qdev_create(NULL, gictype);
|
||||
qdev_prop_set_uint32(gicdev, "revision", 2);
|
||||
@@ -390,15 +390,23 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic)
|
||||
*/
|
||||
for (i = 0; i < smp_cpus; i++) {
|
||||
DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
|
||||
int ppibase = NUM_IRQS + i * 32;
|
||||
/* physical timer; we wire it up to the non-secure timer's ID,
|
||||
* since a real A15 always has TrustZone but QEMU doesn't.
|
||||
int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
|
||||
int irq;
|
||||
/* Mapping from the output timer irq lines from the CPU to the
|
||||
* GIC PPI inputs we use for the virt board.
|
||||
*/
|
||||
qdev_connect_gpio_out(cpudev, 0,
|
||||
qdev_get_gpio_in(gicdev, ppibase + 30));
|
||||
/* virtual timer */
|
||||
qdev_connect_gpio_out(cpudev, 1,
|
||||
qdev_get_gpio_in(gicdev, ppibase + 27));
|
||||
const int timer_irq[] = {
|
||||
[GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
|
||||
[GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
|
||||
[GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
|
||||
[GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
|
||||
};
|
||||
|
||||
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
|
||||
qdev_connect_gpio_out(cpudev, irq,
|
||||
qdev_get_gpio_in(gicdev,
|
||||
ppibase + timer_irq[irq]));
|
||||
}
|
||||
|
||||
sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
|
||||
sysbus_connect_irq(gicbusdev, i + smp_cpus,
|
||||
|
||||
+44
-115
@@ -4,6 +4,7 @@
|
||||
* Copyright (c) 2008 OKL
|
||||
* Originally Written by Hans Jiang
|
||||
* Copyright (c) 2011 NICTA Pty Ltd.
|
||||
* Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
@@ -17,8 +18,7 @@
|
||||
* is a real serial device.
|
||||
*/
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/char/imx_serial.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/char.h"
|
||||
#include "hw/arm/imx.h"
|
||||
@@ -26,7 +26,7 @@
|
||||
//#define DEBUG_SERIAL 1
|
||||
#ifdef DEBUG_SERIAL
|
||||
#define DPRINTF(fmt, args...) \
|
||||
do { printf("imx_serial: " fmt , ##args); } while (0)
|
||||
do { printf("%s: " fmt , TYPE_IMX_SERIAL, ##args); } while (0)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) do {} while (0)
|
||||
#endif
|
||||
@@ -38,42 +38,13 @@ do { printf("imx_serial: " fmt , ##args); } while (0)
|
||||
//#define DEBUG_IMPLEMENTATION 1
|
||||
#ifdef DEBUG_IMPLEMENTATION
|
||||
# define IPRINTF(fmt, args...) \
|
||||
do { fprintf(stderr, "imx_serial: " fmt, ##args); } while (0)
|
||||
do { fprintf(stderr, "%s: " fmt, TYPE_IMX_SERIAL, ##args); } while (0)
|
||||
#else
|
||||
# define IPRINTF(fmt, args...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define TYPE_IMX_SERIAL "imx-serial"
|
||||
#define IMX_SERIAL(obj) OBJECT_CHECK(IMXSerialState, (obj), TYPE_IMX_SERIAL)
|
||||
|
||||
typedef struct IMXSerialState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion iomem;
|
||||
int32_t readbuff;
|
||||
|
||||
uint32_t usr1;
|
||||
uint32_t usr2;
|
||||
uint32_t ucr1;
|
||||
uint32_t ucr2;
|
||||
uint32_t uts1;
|
||||
|
||||
/*
|
||||
* The registers below are implemented just so that the
|
||||
* guest OS sees what it has written
|
||||
*/
|
||||
uint32_t onems;
|
||||
uint32_t ufcr;
|
||||
uint32_t ubmr;
|
||||
uint32_t ubrc;
|
||||
uint32_t ucr3;
|
||||
|
||||
qemu_irq irq;
|
||||
CharDriverState *chr;
|
||||
} IMXSerialState;
|
||||
|
||||
static const VMStateDescription vmstate_imx_serial = {
|
||||
.name = "imx-serial",
|
||||
.name = TYPE_IMX_SERIAL,
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
@@ -91,55 +62,6 @@ static const VMStateDescription vmstate_imx_serial = {
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
#define URXD_CHARRDY (1<<15) /* character read is valid */
|
||||
#define URXD_ERR (1<<14) /* Character has error */
|
||||
#define URXD_BRK (1<<11) /* Break received */
|
||||
|
||||
#define USR1_PARTYER (1<<15) /* Parity Error */
|
||||
#define USR1_RTSS (1<<14) /* RTS pin status */
|
||||
#define USR1_TRDY (1<<13) /* Tx ready */
|
||||
#define USR1_RTSD (1<<12) /* RTS delta: pin changed state */
|
||||
#define USR1_ESCF (1<<11) /* Escape sequence interrupt */
|
||||
#define USR1_FRAMERR (1<<10) /* Framing error */
|
||||
#define USR1_RRDY (1<<9) /* receiver ready */
|
||||
#define USR1_AGTIM (1<<8) /* Aging timer interrupt */
|
||||
#define USR1_DTRD (1<<7) /* DTR changed */
|
||||
#define USR1_RXDS (1<<6) /* Receiver is idle */
|
||||
#define USR1_AIRINT (1<<5) /* Aysnch IR interrupt */
|
||||
#define USR1_AWAKE (1<<4) /* Falling edge detected on RXd pin */
|
||||
|
||||
#define USR2_ADET (1<<15) /* Autobaud complete */
|
||||
#define USR2_TXFE (1<<14) /* Transmit FIFO empty */
|
||||
#define USR2_DTRF (1<<13) /* DTR/DSR transition */
|
||||
#define USR2_IDLE (1<<12) /* UART has been idle for too long */
|
||||
#define USR2_ACST (1<<11) /* Autobaud counter stopped */
|
||||
#define USR2_RIDELT (1<<10) /* Ring Indicator delta */
|
||||
#define USR2_RIIN (1<<9) /* Ring Indicator Input */
|
||||
#define USR2_IRINT (1<<8) /* Serial Infrared Interrupt */
|
||||
#define USR2_WAKE (1<<7) /* Start bit detected */
|
||||
#define USR2_DCDDELT (1<<6) /* Data Carrier Detect delta */
|
||||
#define USR2_DCDIN (1<<5) /* Data Carrier Detect Input */
|
||||
#define USR2_RTSF (1<<4) /* RTS transition */
|
||||
#define USR2_TXDC (1<<3) /* Transmission complete */
|
||||
#define USR2_BRCD (1<<2) /* Break condition detected */
|
||||
#define USR2_ORE (1<<1) /* Overrun error */
|
||||
#define USR2_RDR (1<<0) /* Receive data ready */
|
||||
|
||||
#define UCR1_TRDYEN (1<<13) /* Tx Ready Interrupt Enable */
|
||||
#define UCR1_RRDYEN (1<<9) /* Rx Ready Interrupt Enable */
|
||||
#define UCR1_TXMPTYEN (1<<6) /* Tx Empty Interrupt Enable */
|
||||
#define UCR1_UARTEN (1<<0) /* UART Enable */
|
||||
|
||||
#define UCR2_TXEN (1<<2) /* Transmitter enable */
|
||||
#define UCR2_RXEN (1<<1) /* Receiver enable */
|
||||
#define UCR2_SRST (1<<0) /* Reset complete */
|
||||
|
||||
#define UTS1_TXEMPTY (1<<6)
|
||||
#define UTS1_RXEMPTY (1<<5)
|
||||
#define UTS1_TXFULL (1<<4)
|
||||
#define UTS1_RXFULL (1<<3)
|
||||
|
||||
static void imx_update(IMXSerialState *s)
|
||||
{
|
||||
uint32_t flags;
|
||||
@@ -203,7 +125,9 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
|
||||
s->usr2 &= ~USR2_RDR;
|
||||
s->uts1 |= UTS1_RXEMPTY;
|
||||
imx_update(s);
|
||||
qemu_chr_accept_input(s->chr);
|
||||
if (s->chr) {
|
||||
qemu_chr_accept_input(s->chr);
|
||||
}
|
||||
}
|
||||
return c;
|
||||
|
||||
@@ -242,13 +166,13 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
|
||||
return 0x0; /* TODO */
|
||||
|
||||
default:
|
||||
IPRINTF("imx_serial_read: bad offset: 0x%x\n", (int)offset);
|
||||
IPRINTF("%s: bad offset: 0x%x\n", __func__, (int)offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void imx_serial_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
IMXSerialState *s = (IMXSerialState *)opaque;
|
||||
unsigned char ch;
|
||||
@@ -290,7 +214,9 @@ static void imx_serial_write(void *opaque, hwaddr offset,
|
||||
}
|
||||
if (value & UCR2_RXEN) {
|
||||
if (!(s->ucr2 & UCR2_RXEN)) {
|
||||
qemu_chr_accept_input(s->chr);
|
||||
if (s->chr) {
|
||||
qemu_chr_accept_input(s->chr);
|
||||
}
|
||||
}
|
||||
}
|
||||
s->ucr2 = value & 0xffff;
|
||||
@@ -298,25 +224,25 @@ static void imx_serial_write(void *opaque, hwaddr offset,
|
||||
|
||||
case 0x25: /* USR1 */
|
||||
value &= USR1_AWAKE | USR1_AIRINT | USR1_DTRD | USR1_AGTIM |
|
||||
USR1_FRAMERR | USR1_ESCF | USR1_RTSD | USR1_PARTYER;
|
||||
USR1_FRAMERR | USR1_ESCF | USR1_RTSD | USR1_PARTYER;
|
||||
s->usr1 &= ~value;
|
||||
break;
|
||||
|
||||
case 0x26: /* USR2 */
|
||||
/*
|
||||
* Writing 1 to some bits clears them; all other
|
||||
* values are ignored
|
||||
*/
|
||||
/*
|
||||
* Writing 1 to some bits clears them; all other
|
||||
* values are ignored
|
||||
*/
|
||||
value &= USR2_ADET | USR2_DTRF | USR2_IDLE | USR2_ACST |
|
||||
USR2_RIDELT | USR2_IRINT | USR2_WAKE |
|
||||
USR2_DCDDELT | USR2_RTSF | USR2_BRCD | USR2_ORE;
|
||||
USR2_RIDELT | USR2_IRINT | USR2_WAKE |
|
||||
USR2_DCDDELT | USR2_RTSF | USR2_BRCD | USR2_ORE;
|
||||
s->usr2 &= ~value;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Linux expects to see what it writes to these registers
|
||||
* We don't currently alter the baud rate
|
||||
*/
|
||||
/*
|
||||
* Linux expects to see what it writes to these registers
|
||||
* We don't currently alter the baud rate
|
||||
*/
|
||||
case 0x29: /* UBIR */
|
||||
s->ubrc = value & 0xffff;
|
||||
break;
|
||||
@@ -344,7 +270,7 @@ static void imx_serial_write(void *opaque, hwaddr offset,
|
||||
break;
|
||||
|
||||
default:
|
||||
IPRINTF("imx_serial_write: Bad offset 0x%x\n", (int)offset);
|
||||
IPRINTF("%s: Bad offset 0x%x\n", __func__, (int)offset);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,16 +310,10 @@ static const struct MemoryRegionOps imx_serial_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static int imx_serial_init(SysBusDevice *dev)
|
||||
static void imx_serial_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
IMXSerialState *s = IMX_SERIAL(dev);
|
||||
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &imx_serial_ops, s,
|
||||
"imx-serial", 0x1000);
|
||||
sysbus_init_mmio(dev, &s->iomem);
|
||||
sysbus_init_irq(dev, &s->irq);
|
||||
|
||||
if (s->chr) {
|
||||
qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
|
||||
imx_event, s);
|
||||
@@ -401,8 +321,17 @@ static int imx_serial_init(SysBusDevice *dev)
|
||||
DPRINTF("No char dev for uart at 0x%lx\n",
|
||||
(unsigned long)s->iomem.ram_addr);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
static void imx_serial_init(Object *obj)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
IMXSerialState *s = IMX_SERIAL(obj);
|
||||
|
||||
memory_region_init_io(&s->iomem, obj, &imx_serial_ops, s,
|
||||
TYPE_IMX_SERIAL, 0x1000);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
sysbus_init_irq(sbd, &s->irq);
|
||||
}
|
||||
|
||||
void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq)
|
||||
@@ -439,7 +368,7 @@ void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq)
|
||||
}
|
||||
|
||||
|
||||
static Property imx32_serial_properties[] = {
|
||||
static Property imx_serial_properties[] = {
|
||||
DEFINE_PROP_CHR("chardev", IMXSerialState, chr),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
@@ -447,21 +376,21 @@ static Property imx32_serial_properties[] = {
|
||||
static void imx_serial_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
||||
|
||||
k->init = imx_serial_init;
|
||||
dc->realize = imx_serial_realize;
|
||||
dc->vmsd = &vmstate_imx_serial;
|
||||
dc->reset = imx_serial_reset_at_boot;
|
||||
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
|
||||
dc->desc = "i.MX series UART";
|
||||
dc->props = imx32_serial_properties;
|
||||
dc->props = imx_serial_properties;
|
||||
}
|
||||
|
||||
static const TypeInfo imx_serial_info = {
|
||||
.name = TYPE_IMX_SERIAL,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(IMXSerialState),
|
||||
.class_init = imx_serial_class_init,
|
||||
.name = TYPE_IMX_SERIAL,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(IMXSerialState),
|
||||
.instance_init = imx_serial_init,
|
||||
.class_init = imx_serial_class_init,
|
||||
};
|
||||
|
||||
static void imx_serial_register_types(void)
|
||||
|
||||
+16
-13
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "hw/cpu/a15mpcore.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "kvm_arm.h"
|
||||
|
||||
static void a15mp_priv_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
@@ -33,16 +34,11 @@ static void a15mp_priv_initfn(Object *obj)
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
A15MPPrivState *s = A15MPCORE_PRIV(obj);
|
||||
DeviceState *gicdev;
|
||||
const char *gictype = "arm_gic";
|
||||
|
||||
if (kvm_irqchip_in_kernel()) {
|
||||
gictype = "kvm-arm-gic";
|
||||
}
|
||||
|
||||
memory_region_init(&s->container, obj, "a15mp-priv-container", 0x8000);
|
||||
sysbus_init_mmio(sbd, &s->container);
|
||||
|
||||
object_initialize(&s->gic, sizeof(s->gic), gictype);
|
||||
object_initialize(&s->gic, sizeof(s->gic), gic_class_name());
|
||||
gicdev = DEVICE(&s->gic);
|
||||
qdev_set_parent_bus(gicdev, sysbus_get_default());
|
||||
qdev_prop_set_uint32(gicdev, "revision", 2);
|
||||
@@ -79,14 +75,21 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
|
||||
int ppibase = s->num_irq - 32 + i * 32;
|
||||
/* physical timer; we wire it up to the non-secure timer's ID,
|
||||
* since a real A15 always has TrustZone but QEMU doesn't.
|
||||
int irq;
|
||||
/* Mapping from the output timer irq lines from the CPU to the
|
||||
* GIC PPI inputs used on the A15:
|
||||
*/
|
||||
qdev_connect_gpio_out(cpudev, 0,
|
||||
qdev_get_gpio_in(gicdev, ppibase + 30));
|
||||
/* virtual timer */
|
||||
qdev_connect_gpio_out(cpudev, 1,
|
||||
qdev_get_gpio_in(gicdev, ppibase + 27));
|
||||
const int timer_irq[] = {
|
||||
[GTIMER_PHYS] = 30,
|
||||
[GTIMER_VIRT] = 27,
|
||||
[GTIMER_HYP] = 26,
|
||||
[GTIMER_SEC] = 29,
|
||||
};
|
||||
for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
|
||||
qdev_connect_gpio_out(cpudev, irq,
|
||||
qdev_get_gpio_in(gicdev,
|
||||
ppibase + timer_irq[irq]));
|
||||
}
|
||||
}
|
||||
|
||||
/* Memory map (addresses are offsets from PERIPHBASE):
|
||||
|
||||
+19
-45
@@ -922,12 +922,6 @@ static MemTxResult gic_dist_write(void *opaque, hwaddr offset, uint64_t data,
|
||||
}
|
||||
}
|
||||
|
||||
static const MemoryRegionOps gic_dist_ops = {
|
||||
.read_with_attrs = gic_dist_read,
|
||||
.write_with_attrs = gic_dist_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
|
||||
uint64_t *data, MemTxAttrs attrs)
|
||||
{
|
||||
@@ -1056,10 +1050,17 @@ static MemTxResult gic_do_cpu_write(void *opaque, hwaddr addr,
|
||||
return gic_cpu_write(s, id, addr, value, attrs);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps gic_thiscpu_ops = {
|
||||
.read_with_attrs = gic_thiscpu_read,
|
||||
.write_with_attrs = gic_thiscpu_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
static const MemoryRegionOps gic_ops[2] = {
|
||||
{
|
||||
.read_with_attrs = gic_dist_read,
|
||||
.write_with_attrs = gic_dist_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
},
|
||||
{
|
||||
.read_with_attrs = gic_thiscpu_read,
|
||||
.write_with_attrs = gic_thiscpu_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
}
|
||||
};
|
||||
|
||||
static const MemoryRegionOps gic_cpu_ops = {
|
||||
@@ -1068,31 +1069,10 @@ static const MemoryRegionOps gic_cpu_ops = {
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
/* This function is used by nvic model */
|
||||
void gic_init_irqs_and_distributor(GICState *s)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(s);
|
||||
int i;
|
||||
|
||||
i = s->num_irq - GIC_INTERNAL;
|
||||
/* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
|
||||
* GPIO array layout is thus:
|
||||
* [0..N-1] SPIs
|
||||
* [N..N+31] PPIs for CPU 0
|
||||
* [N+32..N+63] PPIs for CPU 1
|
||||
* ...
|
||||
*/
|
||||
if (s->revision != REV_NVIC) {
|
||||
i += (GIC_INTERNAL * s->num_cpu);
|
||||
}
|
||||
qdev_init_gpio_in(DEVICE(s), gic_set_irq, i);
|
||||
for (i = 0; i < NUM_CPU(s); i++) {
|
||||
sysbus_init_irq(sbd, &s->parent_irq[i]);
|
||||
}
|
||||
for (i = 0; i < NUM_CPU(s); i++) {
|
||||
sysbus_init_irq(sbd, &s->parent_fiq[i]);
|
||||
}
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &gic_dist_ops, s,
|
||||
"gic_dist", 0x1000);
|
||||
gic_init_irqs_and_mmio(s, gic_set_irq, gic_ops);
|
||||
}
|
||||
|
||||
static void arm_gic_realize(DeviceState *dev, Error **errp)
|
||||
@@ -1110,28 +1090,22 @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
gic_init_irqs_and_distributor(s);
|
||||
/* This creates distributor and main CPU interface (s->cpuiomem[0]) */
|
||||
gic_init_irqs_and_mmio(s, gic_set_irq, gic_ops);
|
||||
|
||||
/* Memory regions for the CPU interfaces (NVIC doesn't have these):
|
||||
* a region for "CPU interface for this core", then a region for
|
||||
* "CPU interface for core 0", "for core 1", ...
|
||||
/* Extra core-specific regions for the CPU interfaces. This is
|
||||
* necessary for "franken-GIC" implementations, for example on
|
||||
* Exynos 4.
|
||||
* NB that the memory region size of 0x100 applies for the 11MPCore
|
||||
* and also cores following the GIC v1 spec (ie A9).
|
||||
* GIC v2 defines a larger memory region (0x1000) so this will need
|
||||
* to be extended when we implement A15.
|
||||
*/
|
||||
memory_region_init_io(&s->cpuiomem[0], OBJECT(s), &gic_thiscpu_ops, s,
|
||||
"gic_cpu", 0x100);
|
||||
for (i = 0; i < NUM_CPU(s); i++) {
|
||||
s->backref[i] = s;
|
||||
memory_region_init_io(&s->cpuiomem[i+1], OBJECT(s), &gic_cpu_ops,
|
||||
&s->backref[i], "gic_cpu", 0x100);
|
||||
}
|
||||
/* Distributor */
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
/* cpu interfaces (one for "current cpu" plus one per cpu) */
|
||||
for (i = 0; i <= NUM_CPU(s); i++) {
|
||||
sysbus_init_mmio(sbd, &s->cpuiomem[i]);
|
||||
sysbus_init_mmio(sbd, &s->cpuiomem[i+1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,6 +84,47 @@ static const VMStateDescription vmstate_gic = {
|
||||
}
|
||||
};
|
||||
|
||||
void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
|
||||
const MemoryRegionOps *ops)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(s);
|
||||
int i = s->num_irq - GIC_INTERNAL;
|
||||
|
||||
/* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
|
||||
* GPIO array layout is thus:
|
||||
* [0..N-1] SPIs
|
||||
* [N..N+31] PPIs for CPU 0
|
||||
* [N+32..N+63] PPIs for CPU 1
|
||||
* ...
|
||||
*/
|
||||
if (s->revision != REV_NVIC) {
|
||||
i += (GIC_INTERNAL * s->num_cpu);
|
||||
}
|
||||
qdev_init_gpio_in(DEVICE(s), handler, i);
|
||||
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
sysbus_init_irq(sbd, &s->parent_irq[i]);
|
||||
}
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
sysbus_init_irq(sbd, &s->parent_fiq[i]);
|
||||
}
|
||||
|
||||
/* Distributor */
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), ops, s, "gic_dist", 0x1000);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
|
||||
if (s->revision != REV_NVIC) {
|
||||
/* This is the main CPU interface "for this core". It is always
|
||||
* present because it is required by both software emulation and KVM.
|
||||
* NVIC is not handled here because its CPU interface is different,
|
||||
* neither it can use KVM.
|
||||
*/
|
||||
memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
|
||||
s, "gic_cpu", s->revision == 2 ? 0x1000 : 0x100);
|
||||
sysbus_init_mmio(sbd, &s->cpuiomem[0]);
|
||||
}
|
||||
}
|
||||
|
||||
static void arm_gic_common_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
GICState *s = ARM_GIC_COMMON(dev);
|
||||
|
||||
+1
-27
@@ -543,7 +543,6 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
int i;
|
||||
GICState *s = KVM_ARM_GIC(dev);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
|
||||
Error *local_err = NULL;
|
||||
int ret;
|
||||
@@ -560,32 +559,13 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
|
||||
return;
|
||||
}
|
||||
|
||||
i = s->num_irq - GIC_INTERNAL;
|
||||
/* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
|
||||
* GPIO array layout is thus:
|
||||
* [0..N-1] SPIs
|
||||
* [N..N+31] PPIs for CPU 0
|
||||
* [N+32..N+63] PPIs for CPU 1
|
||||
* ...
|
||||
*/
|
||||
i += (GIC_INTERNAL * s->num_cpu);
|
||||
qdev_init_gpio_in(dev, kvm_arm_gic_set_irq, i);
|
||||
gic_init_irqs_and_mmio(s, kvm_arm_gic_set_irq, NULL);
|
||||
|
||||
for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
|
||||
qemu_irq irq = qdev_get_gpio_in(dev, i);
|
||||
kvm_irqchip_set_qemuirq_gsi(kvm_state, irq, i);
|
||||
}
|
||||
|
||||
/* We never use our outbound IRQ/FIQ lines but provide them so that
|
||||
* we maintain the same interface as the non-KVM GIC.
|
||||
*/
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
sysbus_init_irq(sbd, &s->parent_irq[i]);
|
||||
}
|
||||
for (i = 0; i < s->num_cpu; i++) {
|
||||
sysbus_init_irq(sbd, &s->parent_fiq[i]);
|
||||
}
|
||||
|
||||
/* Try to create the device via the device control API */
|
||||
s->dev_fd = -1;
|
||||
ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V2, false);
|
||||
@@ -609,9 +589,6 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
|
||||
/* Distributor */
|
||||
memory_region_init_reservation(&s->iomem, OBJECT(s),
|
||||
"kvm-gic_dist", 0x1000);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
kvm_arm_register_device(&s->iomem,
|
||||
(KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
|
||||
| KVM_VGIC_V2_ADDR_TYPE_DIST,
|
||||
@@ -622,9 +599,6 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
|
||||
* provide the "interface for core #N" memory regions, because
|
||||
* cores with a VGIC don't have those.
|
||||
*/
|
||||
memory_region_init_reservation(&s->cpuiomem[0], OBJECT(s),
|
||||
"kvm-gic_cpu", 0x1000);
|
||||
sysbus_init_mmio(sbd, &s->cpuiomem[0]);
|
||||
kvm_arm_register_device(&s->cpuiomem[0],
|
||||
(KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
|
||||
| KVM_VGIC_V2_ADDR_TYPE_CPU,
|
||||
|
||||
+10
-46
@@ -7,6 +7,7 @@
|
||||
* Copyright (c) 2008 OKL
|
||||
* Copyright (c) 2011 NICTA Pty Ltd
|
||||
* Originally written by Hans Jiang
|
||||
* Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
*
|
||||
* This code is licensed under the GPL version 2 or later. See
|
||||
* the COPYING file in the top-level directory.
|
||||
@@ -14,16 +15,14 @@
|
||||
* TODO: implement vectors.
|
||||
*/
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "hw/intc/imx_avic.h"
|
||||
|
||||
#define DEBUG_INT 1
|
||||
#undef DEBUG_INT /* comment out for debugging */
|
||||
|
||||
#ifdef DEBUG_INT
|
||||
#define DPRINTF(fmt, args...) \
|
||||
do { printf("imx_avic: " fmt , ##args); } while (0)
|
||||
do { printf("%s: " fmt , TYPE_IMX_AVIC, ##args); } while (0)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) do {} while (0)
|
||||
#endif
|
||||
@@ -35,46 +34,13 @@ do { printf("imx_avic: " fmt , ##args); } while (0)
|
||||
#define DEBUG_IMPLEMENTATION 1
|
||||
#if DEBUG_IMPLEMENTATION
|
||||
# define IPRINTF(fmt, args...) \
|
||||
do { fprintf(stderr, "imx_avic: " fmt, ##args); } while (0)
|
||||
do { fprintf(stderr, "%s: " fmt, TYPE_IMX_AVIC, ##args); } while (0)
|
||||
#else
|
||||
# define IPRINTF(fmt, args...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define IMX_AVIC_NUM_IRQS 64
|
||||
|
||||
/* Interrupt Control Bits */
|
||||
#define ABFLAG (1<<25)
|
||||
#define ABFEN (1<<24)
|
||||
#define NIDIS (1<<22) /* Normal Interrupt disable */
|
||||
#define FIDIS (1<<21) /* Fast interrupt disable */
|
||||
#define NIAD (1<<20) /* Normal Interrupt Arbiter Rise ARM level */
|
||||
#define FIAD (1<<19) /* Fast Interrupt Arbiter Rise ARM level */
|
||||
#define NM (1<<18) /* Normal interrupt mode */
|
||||
|
||||
|
||||
#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4)
|
||||
#define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD)
|
||||
|
||||
#define TYPE_IMX_AVIC "imx_avic"
|
||||
#define IMX_AVIC(obj) \
|
||||
OBJECT_CHECK(IMXAVICState, (obj), TYPE_IMX_AVIC)
|
||||
|
||||
typedef struct IMXAVICState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion iomem;
|
||||
uint64_t pending;
|
||||
uint64_t enabled;
|
||||
uint64_t is_fiq;
|
||||
uint32_t intcntl;
|
||||
uint32_t intmask;
|
||||
qemu_irq irq;
|
||||
qemu_irq fiq;
|
||||
uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */
|
||||
} IMXAVICState;
|
||||
|
||||
static const VMStateDescription vmstate_imx_avic = {
|
||||
.name = "imx-avic",
|
||||
.name = TYPE_IMX_AVIC,
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
@@ -88,8 +54,6 @@ static const VMStateDescription vmstate_imx_avic = {
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
||||
static inline int imx_avic_prio(IMXAVICState *s, int irq)
|
||||
{
|
||||
uint32_t word = irq / PRIO_PER_WORD;
|
||||
@@ -249,7 +213,7 @@ static uint64_t imx_avic_read(void *opaque,
|
||||
return 0x4;
|
||||
|
||||
default:
|
||||
IPRINTF("imx_avic_read: Bad offset 0x%x\n", (int)offset);
|
||||
IPRINTF("%s: Bad offset 0x%x\n", __func__, (int)offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -261,12 +225,12 @@ static void imx_avic_write(void *opaque, hwaddr offset,
|
||||
|
||||
/* Vector Registers not yet supported */
|
||||
if (offset >= 0x100 && offset <= 0x2fc) {
|
||||
IPRINTF("imx_avic_write to vector register %d ignored\n",
|
||||
IPRINTF("%s to vector register %d ignored\n", __func__,
|
||||
(unsigned int)((offset - 0x100) >> 2));
|
||||
return;
|
||||
}
|
||||
|
||||
DPRINTF("imx_avic_write(0x%x) = %x\n",
|
||||
DPRINTF("%s(0x%x) = %x\n", __func__,
|
||||
(unsigned int)offset>>2, (unsigned int)val);
|
||||
switch (offset >> 2) {
|
||||
case 0: /* Interrupt Control Register, INTCNTL */
|
||||
@@ -341,7 +305,7 @@ static void imx_avic_write(void *opaque, hwaddr offset,
|
||||
return;
|
||||
|
||||
default:
|
||||
IPRINTF("imx_avic_write: Bad offset %x\n", (int)offset);
|
||||
IPRINTF("%s: Bad offset %x\n", __func__, (int)offset);
|
||||
}
|
||||
imx_avic_update(s);
|
||||
}
|
||||
@@ -370,7 +334,7 @@ static int imx_avic_init(SysBusDevice *sbd)
|
||||
IMXAVICState *s = IMX_AVIC(dev);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(s), &imx_avic_ops, s,
|
||||
"imx_avic", 0x1000);
|
||||
TYPE_IMX_AVIC, 0x1000);
|
||||
sysbus_init_mmio(sbd, &s->iomem);
|
||||
|
||||
qdev_init_gpio_in(dev, imx_avic_set_irq, IMX_AVIC_NUM_IRQS);
|
||||
|
||||
+8
-73
@@ -2,6 +2,7 @@
|
||||
* IMX31 Clock Control Module
|
||||
*
|
||||
* Copyright (C) 2012 NICTA
|
||||
* Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
@@ -10,51 +11,23 @@
|
||||
* the CCM.
|
||||
*/
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/arm/imx.h"
|
||||
#include "hw/misc/imx_ccm.h"
|
||||
|
||||
#define CKIH_FREQ 26000000 /* 26MHz crystal input */
|
||||
#define CKIL_FREQ 32768 /* nominal 32khz clock */
|
||||
|
||||
|
||||
//#define DEBUG_CCM 1
|
||||
#ifdef DEBUG_CCM
|
||||
#define DPRINTF(fmt, args...) \
|
||||
do { printf("imx_ccm: " fmt , ##args); } while (0)
|
||||
do { printf("%s: " fmt , TYPE_IMX_CCM, ##args); } while (0)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) do {} while (0)
|
||||
#endif
|
||||
|
||||
static int imx_ccm_post_load(void *opaque, int version_id);
|
||||
|
||||
#define TYPE_IMX_CCM "imx_ccm"
|
||||
#define IMX_CCM(obj) OBJECT_CHECK(IMXCCMState, (obj), TYPE_IMX_CCM)
|
||||
|
||||
typedef struct IMXCCMState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion iomem;
|
||||
|
||||
uint32_t ccmr;
|
||||
uint32_t pdr0;
|
||||
uint32_t pdr1;
|
||||
uint32_t mpctl;
|
||||
uint32_t spctl;
|
||||
uint32_t cgr[3];
|
||||
uint32_t pmcr0;
|
||||
uint32_t pmcr1;
|
||||
|
||||
/* Frequencies precalculated on register changes */
|
||||
uint32_t pll_refclk_freq;
|
||||
uint32_t mcu_clk_freq;
|
||||
uint32_t hsp_clk_freq;
|
||||
uint32_t ipg_clk_freq;
|
||||
} IMXCCMState;
|
||||
|
||||
static const VMStateDescription vmstate_imx_ccm = {
|
||||
.name = "imx-ccm",
|
||||
.name = TYPE_IMX_CCM,
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
@@ -72,44 +45,6 @@ static const VMStateDescription vmstate_imx_ccm = {
|
||||
.post_load = imx_ccm_post_load,
|
||||
};
|
||||
|
||||
/* CCMR */
|
||||
#define CCMR_FPME (1<<0)
|
||||
#define CCMR_MPE (1<<3)
|
||||
#define CCMR_MDS (1<<7)
|
||||
#define CCMR_FPMF (1<<26)
|
||||
#define CCMR_PRCS (3<<1)
|
||||
|
||||
/* PDR0 */
|
||||
#define PDR0_MCU_PODF_SHIFT (0)
|
||||
#define PDR0_MCU_PODF_MASK (0x7)
|
||||
#define PDR0_MAX_PODF_SHIFT (3)
|
||||
#define PDR0_MAX_PODF_MASK (0x7)
|
||||
#define PDR0_IPG_PODF_SHIFT (6)
|
||||
#define PDR0_IPG_PODF_MASK (0x3)
|
||||
#define PDR0_NFC_PODF_SHIFT (8)
|
||||
#define PDR0_NFC_PODF_MASK (0x7)
|
||||
#define PDR0_HSP_PODF_SHIFT (11)
|
||||
#define PDR0_HSP_PODF_MASK (0x7)
|
||||
#define PDR0_PER_PODF_SHIFT (16)
|
||||
#define PDR0_PER_PODF_MASK (0x1f)
|
||||
#define PDR0_CSI_PODF_SHIFT (23)
|
||||
#define PDR0_CSI_PODF_MASK (0x1ff)
|
||||
|
||||
#define EXTRACT(value, name) (((value) >> PDR0_##name##_PODF_SHIFT) \
|
||||
& PDR0_##name##_PODF_MASK)
|
||||
#define INSERT(value, name) (((value) & PDR0_##name##_PODF_MASK) << \
|
||||
PDR0_##name##_PODF_SHIFT)
|
||||
/* PLL control registers */
|
||||
#define PD(v) (((v) >> 26) & 0xf)
|
||||
#define MFD(v) (((v) >> 16) & 0x3ff)
|
||||
#define MFI(v) (((v) >> 10) & 0xf);
|
||||
#define MFN(v) ((v) & 0x3ff)
|
||||
|
||||
#define PLL_PD(x) (((x) & 0xf) << 26)
|
||||
#define PLL_MFD(x) (((x) & 0x3ff) << 16)
|
||||
#define PLL_MFI(x) (((x) & 0xf) << 10)
|
||||
#define PLL_MFN(x) (((x) & 0x3ff) << 0)
|
||||
|
||||
uint32_t imx_clock_frequency(DeviceState *dev, IMXClk clock)
|
||||
{
|
||||
IMXCCMState *s = IMX_CCM(dev);
|
||||
@@ -174,7 +109,7 @@ static void update_clocks(IMXCCMState *s)
|
||||
s->hsp_clk_freq = s->mcu_clk_freq / (1 + EXTRACT(s->pdr0, HSP));
|
||||
s->ipg_clk_freq = s->hsp_clk_freq / (1 + EXTRACT(s->pdr0, IPG));
|
||||
|
||||
DPRINTF("Clocks: mcu %uMHz, HSP %uMHz, IPG %uHz\n",
|
||||
DPRINTF("%s: mcu %uMHz, HSP %uMHz, IPG %uHz\n", __func__,
|
||||
s->mcu_clk_freq / 1000000,
|
||||
s->hsp_clk_freq / 1000000,
|
||||
s->ipg_clk_freq);
|
||||
@@ -200,7 +135,7 @@ static uint64_t imx_ccm_read(void *opaque, hwaddr offset,
|
||||
{
|
||||
IMXCCMState *s = (IMXCCMState *)opaque;
|
||||
|
||||
DPRINTF("read(offset=%x)", offset >> 2);
|
||||
DPRINTF("%s(offset=%x)", __func__, offset >> 2);
|
||||
switch (offset >> 2) {
|
||||
case 0: /* CCMR */
|
||||
DPRINTF(" ccmr = 0x%x\n", s->ccmr);
|
||||
@@ -241,7 +176,7 @@ static void imx_ccm_write(void *opaque, hwaddr offset,
|
||||
{
|
||||
IMXCCMState *s = (IMXCCMState *)opaque;
|
||||
|
||||
DPRINTF("write(offset=%x, value = %x)\n",
|
||||
DPRINTF("%s(offset=%x, value = %x)\n", __func__,
|
||||
offset >> 2, (unsigned int)value);
|
||||
switch (offset >> 2) {
|
||||
case 0:
|
||||
@@ -286,7 +221,7 @@ static int imx_ccm_init(SysBusDevice *dev)
|
||||
IMXCCMState *s = IMX_CCM(dev);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(dev), &imx_ccm_ops, s,
|
||||
"imx_ccm", 0x1000);
|
||||
TYPE_IMX_CCM, 0x1000);
|
||||
sysbus_init_mmio(dev, &s->iomem);
|
||||
|
||||
return 0;
|
||||
|
||||
+9
-55
@@ -5,23 +5,18 @@
|
||||
* Copyright (c) 2011 NICTA Pty Ltd
|
||||
* Originally written by Hans Jiang
|
||||
* Updated by Peter Chubb
|
||||
* Updated by Jean-Christophe Dubois
|
||||
* Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
*
|
||||
* This code is licensed under GPL version 2 or later. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/ptimer.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/arm/imx.h"
|
||||
#include "hw/timer/imx_epit.h"
|
||||
#include "hw/misc/imx_ccm.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
#define TYPE_IMX_EPIT "imx.epit"
|
||||
|
||||
#define DEBUG_TIMER 0
|
||||
#if DEBUG_TIMER
|
||||
|
||||
@@ -61,30 +56,6 @@ static char const *imx_epit_reg_name(uint32_t reg)
|
||||
# define IPRINTF(fmt, args...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define IMX_EPIT(obj) \
|
||||
OBJECT_CHECK(IMXEPITState, (obj), TYPE_IMX_EPIT)
|
||||
|
||||
/*
|
||||
* EPIT: Enhanced periodic interrupt timer
|
||||
*/
|
||||
|
||||
#define CR_EN (1 << 0)
|
||||
#define CR_ENMOD (1 << 1)
|
||||
#define CR_OCIEN (1 << 2)
|
||||
#define CR_RLD (1 << 3)
|
||||
#define CR_PRESCALE_SHIFT (4)
|
||||
#define CR_PRESCALE_MASK (0xfff)
|
||||
#define CR_SWR (1 << 16)
|
||||
#define CR_IOVW (1 << 17)
|
||||
#define CR_DBGEN (1 << 18)
|
||||
#define CR_WAITEN (1 << 19)
|
||||
#define CR_DOZEN (1 << 20)
|
||||
#define CR_STOPEN (1 << 21)
|
||||
#define CR_CLKSRC_SHIFT (24)
|
||||
#define CR_CLKSRC_MASK (0x3 << CR_CLKSRC_SHIFT)
|
||||
|
||||
#define EPIT_TIMER_MAX 0XFFFFFFFFUL
|
||||
|
||||
/*
|
||||
* Exact clock frequencies vary from board to board.
|
||||
* These are typical.
|
||||
@@ -96,23 +67,6 @@ static const IMXClk imx_epit_clocks[] = {
|
||||
CLK_32k, /* 11 ipg_clk_32k -- ~32kHz */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
SysBusDevice busdev;
|
||||
ptimer_state *timer_reload;
|
||||
ptimer_state *timer_cmp;
|
||||
MemoryRegion iomem;
|
||||
DeviceState *ccm;
|
||||
|
||||
uint32_t cr;
|
||||
uint32_t sr;
|
||||
uint32_t lr;
|
||||
uint32_t cmp;
|
||||
uint32_t cnt;
|
||||
|
||||
uint32_t freq;
|
||||
qemu_irq irq;
|
||||
} IMXEPITState;
|
||||
|
||||
/*
|
||||
* Update interrupt status
|
||||
*/
|
||||
@@ -174,9 +128,9 @@ static void imx_epit_reset(DeviceState *dev)
|
||||
|
||||
static uint32_t imx_epit_update_count(IMXEPITState *s)
|
||||
{
|
||||
s->cnt = ptimer_get_count(s->timer_reload);
|
||||
s->cnt = ptimer_get_count(s->timer_reload);
|
||||
|
||||
return s->cnt;
|
||||
return s->cnt;
|
||||
}
|
||||
|
||||
static uint64_t imx_epit_read(void *opaque, hwaddr offset, unsigned size)
|
||||
@@ -344,13 +298,13 @@ void imx_timerp_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm)
|
||||
}
|
||||
|
||||
static const MemoryRegionOps imx_epit_ops = {
|
||||
.read = imx_epit_read,
|
||||
.write = imx_epit_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.read = imx_epit_read,
|
||||
.write = imx_epit_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_imx_timer_epit = {
|
||||
.name = "imx.epit",
|
||||
.name = TYPE_IMX_EPIT,
|
||||
.version_id = 2,
|
||||
.minimum_version_id = 2,
|
||||
.fields = (VMStateField[]) {
|
||||
|
||||
+6
-79
@@ -5,23 +5,18 @@
|
||||
* Copyright (c) 2011 NICTA Pty Ltd
|
||||
* Originally written by Hans Jiang
|
||||
* Updated by Peter Chubb
|
||||
* Updated by Jean-Christophe Dubois
|
||||
* Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
*
|
||||
* This code is licensed under GPL version 2 or later. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/ptimer.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/arm/imx.h"
|
||||
#include "hw/timer/imx_gpt.h"
|
||||
#include "hw/misc/imx_ccm.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
#define TYPE_IMX_GPT "imx.gpt"
|
||||
|
||||
/*
|
||||
* Define to 1 for debug messages
|
||||
*/
|
||||
@@ -74,76 +69,8 @@ static char const *imx_gpt_reg_name(uint32_t reg)
|
||||
# define IPRINTF(fmt, args...) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define IMX_GPT(obj) \
|
||||
OBJECT_CHECK(IMXGPTState, (obj), TYPE_IMX_GPT)
|
||||
/*
|
||||
* GPT : General purpose timer
|
||||
*
|
||||
* This timer counts up continuously while it is enabled, resetting itself
|
||||
* to 0 when it reaches GPT_TIMER_MAX (in freerun mode) or when it
|
||||
* reaches the value of one of the ocrX (in periodic mode).
|
||||
*/
|
||||
|
||||
#define GPT_TIMER_MAX 0XFFFFFFFFUL
|
||||
|
||||
/* Control register. Not all of these bits have any effect (yet) */
|
||||
#define GPT_CR_EN (1 << 0) /* GPT Enable */
|
||||
#define GPT_CR_ENMOD (1 << 1) /* GPT Enable Mode */
|
||||
#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */
|
||||
#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */
|
||||
#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */
|
||||
#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */
|
||||
#define GPT_CR_CLKSRC_SHIFT (6)
|
||||
#define GPT_CR_CLKSRC_MASK (0x7)
|
||||
|
||||
#define GPT_CR_FRR (1 << 9) /* Freerun or Restart */
|
||||
#define GPT_CR_SWR (1 << 15) /* Software Reset */
|
||||
#define GPT_CR_IM1 (3 << 16) /* Input capture channel 1 mode (2 bits) */
|
||||
#define GPT_CR_IM2 (3 << 18) /* Input capture channel 2 mode (2 bits) */
|
||||
#define GPT_CR_OM1 (7 << 20) /* Output Compare Channel 1 Mode (3 bits) */
|
||||
#define GPT_CR_OM2 (7 << 23) /* Output Compare Channel 2 Mode (3 bits) */
|
||||
#define GPT_CR_OM3 (7 << 26) /* Output Compare Channel 3 Mode (3 bits) */
|
||||
#define GPT_CR_FO1 (1 << 29) /* Force Output Compare Channel 1 */
|
||||
#define GPT_CR_FO2 (1 << 30) /* Force Output Compare Channel 2 */
|
||||
#define GPT_CR_FO3 (1 << 31) /* Force Output Compare Channel 3 */
|
||||
|
||||
#define GPT_SR_OF1 (1 << 0)
|
||||
#define GPT_SR_OF2 (1 << 1)
|
||||
#define GPT_SR_OF3 (1 << 2)
|
||||
#define GPT_SR_ROV (1 << 5)
|
||||
|
||||
#define GPT_IR_OF1IE (1 << 0)
|
||||
#define GPT_IR_OF2IE (1 << 1)
|
||||
#define GPT_IR_OF3IE (1 << 2)
|
||||
#define GPT_IR_ROVIE (1 << 5)
|
||||
|
||||
typedef struct {
|
||||
SysBusDevice busdev;
|
||||
ptimer_state *timer;
|
||||
MemoryRegion iomem;
|
||||
DeviceState *ccm;
|
||||
|
||||
uint32_t cr;
|
||||
uint32_t pr;
|
||||
uint32_t sr;
|
||||
uint32_t ir;
|
||||
uint32_t ocr1;
|
||||
uint32_t ocr2;
|
||||
uint32_t ocr3;
|
||||
uint32_t icr1;
|
||||
uint32_t icr2;
|
||||
uint32_t cnt;
|
||||
|
||||
uint32_t next_timeout;
|
||||
uint32_t next_int;
|
||||
|
||||
uint32_t freq;
|
||||
|
||||
qemu_irq irq;
|
||||
} IMXGPTState;
|
||||
|
||||
static const VMStateDescription vmstate_imx_timer_gpt = {
|
||||
.name = "imx.gpt",
|
||||
.name = TYPE_IMX_GPT,
|
||||
.version_id = 3,
|
||||
.minimum_version_id = 3,
|
||||
.fields = (VMStateField[]) {
|
||||
@@ -180,7 +107,7 @@ static void imx_gpt_set_freq(IMXGPTState *s)
|
||||
{
|
||||
uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3);
|
||||
uint32_t freq = imx_clock_frequency(s->ccm, imx_gpt_clocks[clksrc])
|
||||
/ (1 + s->pr);
|
||||
/ (1 + s->pr);
|
||||
s->freq = freq;
|
||||
|
||||
DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, freq);
|
||||
@@ -207,7 +134,7 @@ static uint32_t imx_gpt_update_count(IMXGPTState *s)
|
||||
}
|
||||
|
||||
static inline uint32_t imx_gpt_find_limit(uint32_t count, uint32_t reg,
|
||||
uint32_t timeout)
|
||||
uint32_t timeout)
|
||||
{
|
||||
if ((count < reg) && (timeout > reg)) {
|
||||
timeout = reg;
|
||||
|
||||
+11
-3
@@ -437,6 +437,9 @@ void memory_region_init_alias(MemoryRegion *mr,
|
||||
* memory_region_init_rom_device: Initialize a ROM memory region. Writes are
|
||||
* handled via callbacks.
|
||||
*
|
||||
* If NULL callbacks pointer is given, then I/O space is not supposed to be
|
||||
* handled by QEMU itself. Any access via the memory API will cause an abort().
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized.
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @ops: callbacks for write access handling.
|
||||
@@ -459,16 +462,21 @@ void memory_region_init_rom_device(MemoryRegion *mr,
|
||||
* A reservation region primariy serves debugging purposes. It claims I/O
|
||||
* space that is not supposed to be handled by QEMU itself. Any access via
|
||||
* the memory API will cause an abort().
|
||||
* This function is deprecated. Use memory_region_init_io() with NULL
|
||||
* callbacks instead.
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @name: used for debugging; not visible to the user or ABI
|
||||
* @size: size of the region.
|
||||
*/
|
||||
void memory_region_init_reservation(MemoryRegion *mr,
|
||||
struct Object *owner,
|
||||
static inline void memory_region_init_reservation(MemoryRegion *mr,
|
||||
Object *owner,
|
||||
const char *name,
|
||||
uint64_t size);
|
||||
uint64_t size)
|
||||
{
|
||||
memory_region_init_io(mr, owner, NULL, mr, name, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* memory_region_init_iommu: Initialize a memory region that translates
|
||||
|
||||
+2
-10
@@ -11,18 +11,10 @@
|
||||
#ifndef IMX_H
|
||||
#define IMX_H
|
||||
|
||||
#include "hw/misc/imx_ccm.h"
|
||||
|
||||
void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq);
|
||||
|
||||
typedef enum {
|
||||
NOCLK,
|
||||
MCU,
|
||||
HSP,
|
||||
IPG,
|
||||
CLK_32k
|
||||
} IMXClk;
|
||||
|
||||
uint32_t imx_clock_frequency(DeviceState *s, IMXClk clock);
|
||||
|
||||
void imx_timerp_create(const hwaddr addr,
|
||||
qemu_irq irq,
|
||||
DeviceState *ccm);
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Device model for i.MX UART
|
||||
*
|
||||
* Copyright (c) 2008 OKL
|
||||
* Originally Written by Hans Jiang
|
||||
* Copyright (c) 2011 NICTA Pty Ltd.
|
||||
* Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef IMX_SERIAL_H
|
||||
#define IMX_SERIAL_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_IMX_SERIAL "imx.serial"
|
||||
#define IMX_SERIAL(obj) OBJECT_CHECK(IMXSerialState, (obj), TYPE_IMX_SERIAL)
|
||||
|
||||
#define URXD_CHARRDY (1<<15) /* character read is valid */
|
||||
#define URXD_ERR (1<<14) /* Character has error */
|
||||
#define URXD_BRK (1<<11) /* Break received */
|
||||
|
||||
#define USR1_PARTYER (1<<15) /* Parity Error */
|
||||
#define USR1_RTSS (1<<14) /* RTS pin status */
|
||||
#define USR1_TRDY (1<<13) /* Tx ready */
|
||||
#define USR1_RTSD (1<<12) /* RTS delta: pin changed state */
|
||||
#define USR1_ESCF (1<<11) /* Escape sequence interrupt */
|
||||
#define USR1_FRAMERR (1<<10) /* Framing error */
|
||||
#define USR1_RRDY (1<<9) /* receiver ready */
|
||||
#define USR1_AGTIM (1<<8) /* Aging timer interrupt */
|
||||
#define USR1_DTRD (1<<7) /* DTR changed */
|
||||
#define USR1_RXDS (1<<6) /* Receiver is idle */
|
||||
#define USR1_AIRINT (1<<5) /* Aysnch IR interrupt */
|
||||
#define USR1_AWAKE (1<<4) /* Falling edge detected on RXd pin */
|
||||
|
||||
#define USR2_ADET (1<<15) /* Autobaud complete */
|
||||
#define USR2_TXFE (1<<14) /* Transmit FIFO empty */
|
||||
#define USR2_DTRF (1<<13) /* DTR/DSR transition */
|
||||
#define USR2_IDLE (1<<12) /* UART has been idle for too long */
|
||||
#define USR2_ACST (1<<11) /* Autobaud counter stopped */
|
||||
#define USR2_RIDELT (1<<10) /* Ring Indicator delta */
|
||||
#define USR2_RIIN (1<<9) /* Ring Indicator Input */
|
||||
#define USR2_IRINT (1<<8) /* Serial Infrared Interrupt */
|
||||
#define USR2_WAKE (1<<7) /* Start bit detected */
|
||||
#define USR2_DCDDELT (1<<6) /* Data Carrier Detect delta */
|
||||
#define USR2_DCDIN (1<<5) /* Data Carrier Detect Input */
|
||||
#define USR2_RTSF (1<<4) /* RTS transition */
|
||||
#define USR2_TXDC (1<<3) /* Transmission complete */
|
||||
#define USR2_BRCD (1<<2) /* Break condition detected */
|
||||
#define USR2_ORE (1<<1) /* Overrun error */
|
||||
#define USR2_RDR (1<<0) /* Receive data ready */
|
||||
|
||||
#define UCR1_TRDYEN (1<<13) /* Tx Ready Interrupt Enable */
|
||||
#define UCR1_RRDYEN (1<<9) /* Rx Ready Interrupt Enable */
|
||||
#define UCR1_TXMPTYEN (1<<6) /* Tx Empty Interrupt Enable */
|
||||
#define UCR1_UARTEN (1<<0) /* UART Enable */
|
||||
|
||||
#define UCR2_TXEN (1<<2) /* Transmitter enable */
|
||||
#define UCR2_RXEN (1<<1) /* Receiver enable */
|
||||
#define UCR2_SRST (1<<0) /* Reset complete */
|
||||
|
||||
#define UTS1_TXEMPTY (1<<6)
|
||||
#define UTS1_RXEMPTY (1<<5)
|
||||
#define UTS1_TXFULL (1<<4)
|
||||
#define UTS1_RXFULL (1<<3)
|
||||
|
||||
typedef struct IMXSerialState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
MemoryRegion iomem;
|
||||
int32_t readbuff;
|
||||
|
||||
uint32_t usr1;
|
||||
uint32_t usr2;
|
||||
uint32_t ucr1;
|
||||
uint32_t ucr2;
|
||||
uint32_t uts1;
|
||||
|
||||
/*
|
||||
* The registers below are implemented just so that the
|
||||
* guest OS sees what it has written
|
||||
*/
|
||||
uint32_t onems;
|
||||
uint32_t ufcr;
|
||||
uint32_t ubmr;
|
||||
uint32_t ubrc;
|
||||
uint32_t ucr3;
|
||||
|
||||
qemu_irq irq;
|
||||
CharDriverState *chr;
|
||||
} IMXSerialState;
|
||||
|
||||
#endif
|
||||
@@ -138,4 +138,7 @@ typedef struct ARMGICCommonClass {
|
||||
void (*post_load)(GICState *s);
|
||||
} ARMGICCommonClass;
|
||||
|
||||
void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
|
||||
const MemoryRegionOps *ops);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* i.MX31 Vectored Interrupt Controller
|
||||
*
|
||||
* Note this is NOT the PL192 provided by ARM, but
|
||||
* a custom implementation by Freescale.
|
||||
*
|
||||
* Copyright (c) 2008 OKL
|
||||
* Copyright (c) 2011 NICTA Pty Ltd
|
||||
* Originally written by Hans Jiang
|
||||
* Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
*
|
||||
* This code is licensed under the GPL version 2 or later. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
* TODO: implement vectors.
|
||||
*/
|
||||
#ifndef IMX_AVIC_H
|
||||
#define IMX_AVIC_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
#define TYPE_IMX_AVIC "imx.avic"
|
||||
#define IMX_AVIC(obj) OBJECT_CHECK(IMXAVICState, (obj), TYPE_IMX_AVIC)
|
||||
|
||||
#define IMX_AVIC_NUM_IRQS 64
|
||||
|
||||
/* Interrupt Control Bits */
|
||||
#define ABFLAG (1<<25)
|
||||
#define ABFEN (1<<24)
|
||||
#define NIDIS (1<<22) /* Normal Interrupt disable */
|
||||
#define FIDIS (1<<21) /* Fast interrupt disable */
|
||||
#define NIAD (1<<20) /* Normal Interrupt Arbiter Rise ARM level */
|
||||
#define FIAD (1<<19) /* Fast Interrupt Arbiter Rise ARM level */
|
||||
#define NM (1<<18) /* Normal interrupt mode */
|
||||
|
||||
#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4)
|
||||
#define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD)
|
||||
|
||||
typedef struct IMXAVICState{
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
MemoryRegion iomem;
|
||||
uint64_t pending;
|
||||
uint64_t enabled;
|
||||
uint64_t is_fiq;
|
||||
uint32_t intcntl;
|
||||
uint32_t intmask;
|
||||
qemu_irq irq;
|
||||
qemu_irq fiq;
|
||||
uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */
|
||||
} IMXAVICState;
|
||||
|
||||
#endif /* IMX_AVIC_H */
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* IMX31 Clock Control Module
|
||||
*
|
||||
* Copyright (C) 2012 NICTA
|
||||
* Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef IMX_CCM_H
|
||||
#define IMX_CCM_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
/* CCMR */
|
||||
#define CCMR_FPME (1<<0)
|
||||
#define CCMR_MPE (1<<3)
|
||||
#define CCMR_MDS (1<<7)
|
||||
#define CCMR_FPMF (1<<26)
|
||||
#define CCMR_PRCS (3<<1)
|
||||
|
||||
/* PDR0 */
|
||||
#define PDR0_MCU_PODF_SHIFT (0)
|
||||
#define PDR0_MCU_PODF_MASK (0x7)
|
||||
#define PDR0_MAX_PODF_SHIFT (3)
|
||||
#define PDR0_MAX_PODF_MASK (0x7)
|
||||
#define PDR0_IPG_PODF_SHIFT (6)
|
||||
#define PDR0_IPG_PODF_MASK (0x3)
|
||||
#define PDR0_NFC_PODF_SHIFT (8)
|
||||
#define PDR0_NFC_PODF_MASK (0x7)
|
||||
#define PDR0_HSP_PODF_SHIFT (11)
|
||||
#define PDR0_HSP_PODF_MASK (0x7)
|
||||
#define PDR0_PER_PODF_SHIFT (16)
|
||||
#define PDR0_PER_PODF_MASK (0x1f)
|
||||
#define PDR0_CSI_PODF_SHIFT (23)
|
||||
#define PDR0_CSI_PODF_MASK (0x1ff)
|
||||
|
||||
#define EXTRACT(value, name) (((value) >> PDR0_##name##_PODF_SHIFT) \
|
||||
& PDR0_##name##_PODF_MASK)
|
||||
#define INSERT(value, name) (((value) & PDR0_##name##_PODF_MASK) << \
|
||||
PDR0_##name##_PODF_SHIFT)
|
||||
|
||||
/* PLL control registers */
|
||||
#define PD(v) (((v) >> 26) & 0xf)
|
||||
#define MFD(v) (((v) >> 16) & 0x3ff)
|
||||
#define MFI(v) (((v) >> 10) & 0xf);
|
||||
#define MFN(v) ((v) & 0x3ff)
|
||||
|
||||
#define PLL_PD(x) (((x) & 0xf) << 26)
|
||||
#define PLL_MFD(x) (((x) & 0x3ff) << 16)
|
||||
#define PLL_MFI(x) (((x) & 0xf) << 10)
|
||||
#define PLL_MFN(x) (((x) & 0x3ff) << 0)
|
||||
|
||||
#define TYPE_IMX_CCM "imx.ccm"
|
||||
#define IMX_CCM(obj) OBJECT_CHECK(IMXCCMState, (obj), TYPE_IMX_CCM)
|
||||
|
||||
typedef struct IMXCCMState {
|
||||
/* <private> */
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/* <public> */
|
||||
MemoryRegion iomem;
|
||||
|
||||
uint32_t ccmr;
|
||||
uint32_t pdr0;
|
||||
uint32_t pdr1;
|
||||
uint32_t mpctl;
|
||||
uint32_t spctl;
|
||||
uint32_t cgr[3];
|
||||
uint32_t pmcr0;
|
||||
uint32_t pmcr1;
|
||||
|
||||
/* Frequencies precalculated on register changes */
|
||||
uint32_t pll_refclk_freq;
|
||||
uint32_t mcu_clk_freq;
|
||||
uint32_t hsp_clk_freq;
|
||||
uint32_t ipg_clk_freq;
|
||||
} IMXCCMState;
|
||||
|
||||
typedef enum {
|
||||
NOCLK,
|
||||
MCU,
|
||||
HSP,
|
||||
IPG,
|
||||
CLK_32k
|
||||
} IMXClk;
|
||||
|
||||
uint32_t imx_clock_frequency(DeviceState *s, IMXClk clock);
|
||||
|
||||
#endif /* IMX_CCM_H */
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* i.MX EPIT Timer
|
||||
*
|
||||
* Copyright (c) 2008 OK Labs
|
||||
* Copyright (c) 2011 NICTA Pty Ltd
|
||||
* Originally written by Hans Jiang
|
||||
* Updated by Peter Chubb
|
||||
* Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef IMX_EPIT_H
|
||||
#define IMX_EPIT_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/ptimer.h"
|
||||
|
||||
/*
|
||||
* EPIT: Enhanced periodic interrupt timer
|
||||
*/
|
||||
|
||||
#define CR_EN (1 << 0)
|
||||
#define CR_ENMOD (1 << 1)
|
||||
#define CR_OCIEN (1 << 2)
|
||||
#define CR_RLD (1 << 3)
|
||||
#define CR_PRESCALE_SHIFT (4)
|
||||
#define CR_PRESCALE_MASK (0xfff)
|
||||
#define CR_SWR (1 << 16)
|
||||
#define CR_IOVW (1 << 17)
|
||||
#define CR_DBGEN (1 << 18)
|
||||
#define CR_WAITEN (1 << 19)
|
||||
#define CR_DOZEN (1 << 20)
|
||||
#define CR_STOPEN (1 << 21)
|
||||
#define CR_CLKSRC_SHIFT (24)
|
||||
#define CR_CLKSRC_MASK (0x3 << CR_CLKSRC_SHIFT)
|
||||
|
||||
#define EPIT_TIMER_MAX 0XFFFFFFFFUL
|
||||
|
||||
#define TYPE_IMX_EPIT "imx.epit"
|
||||
#define IMX_EPIT(obj) OBJECT_CHECK(IMXEPITState, (obj), TYPE_IMX_EPIT)
|
||||
|
||||
typedef struct IMXEPITState{
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
ptimer_state *timer_reload;
|
||||
ptimer_state *timer_cmp;
|
||||
MemoryRegion iomem;
|
||||
DeviceState *ccm;
|
||||
|
||||
uint32_t cr;
|
||||
uint32_t sr;
|
||||
uint32_t lr;
|
||||
uint32_t cmp;
|
||||
uint32_t cnt;
|
||||
|
||||
uint32_t freq;
|
||||
qemu_irq irq;
|
||||
} IMXEPITState;
|
||||
|
||||
#endif /* IMX_EPIT_H */
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* i.MX GPT Timer
|
||||
*
|
||||
* Copyright (c) 2008 OK Labs
|
||||
* Copyright (c) 2011 NICTA Pty Ltd
|
||||
* Originally written by Hans Jiang
|
||||
* Updated by Peter Chubb
|
||||
* Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef IMX_GPT_H
|
||||
#define IMX_GPT_H
|
||||
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/ptimer.h"
|
||||
|
||||
/*
|
||||
* GPT : General purpose timer
|
||||
*
|
||||
* This timer counts up continuously while it is enabled, resetting itself
|
||||
* to 0 when it reaches GPT_TIMER_MAX (in freerun mode) or when it
|
||||
* reaches the value of one of the ocrX (in periodic mode).
|
||||
*/
|
||||
|
||||
#define GPT_TIMER_MAX 0XFFFFFFFFUL
|
||||
|
||||
/* Control register. Not all of these bits have any effect (yet) */
|
||||
#define GPT_CR_EN (1 << 0) /* GPT Enable */
|
||||
#define GPT_CR_ENMOD (1 << 1) /* GPT Enable Mode */
|
||||
#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */
|
||||
#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */
|
||||
#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */
|
||||
#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */
|
||||
#define GPT_CR_CLKSRC_SHIFT (6)
|
||||
#define GPT_CR_CLKSRC_MASK (0x7)
|
||||
|
||||
#define GPT_CR_FRR (1 << 9) /* Freerun or Restart */
|
||||
#define GPT_CR_SWR (1 << 15) /* Software Reset */
|
||||
#define GPT_CR_IM1 (3 << 16) /* Input capture channel 1 mode (2 bits) */
|
||||
#define GPT_CR_IM2 (3 << 18) /* Input capture channel 2 mode (2 bits) */
|
||||
#define GPT_CR_OM1 (7 << 20) /* Output Compare Channel 1 Mode (3 bits) */
|
||||
#define GPT_CR_OM2 (7 << 23) /* Output Compare Channel 2 Mode (3 bits) */
|
||||
#define GPT_CR_OM3 (7 << 26) /* Output Compare Channel 3 Mode (3 bits) */
|
||||
#define GPT_CR_FO1 (1 << 29) /* Force Output Compare Channel 1 */
|
||||
#define GPT_CR_FO2 (1 << 30) /* Force Output Compare Channel 2 */
|
||||
#define GPT_CR_FO3 (1 << 31) /* Force Output Compare Channel 3 */
|
||||
|
||||
#define GPT_SR_OF1 (1 << 0)
|
||||
#define GPT_SR_OF2 (1 << 1)
|
||||
#define GPT_SR_OF3 (1 << 2)
|
||||
#define GPT_SR_ROV (1 << 5)
|
||||
|
||||
#define GPT_IR_OF1IE (1 << 0)
|
||||
#define GPT_IR_OF2IE (1 << 1)
|
||||
#define GPT_IR_OF3IE (1 << 2)
|
||||
#define GPT_IR_ROVIE (1 << 5)
|
||||
|
||||
#define TYPE_IMX_GPT "imx.gpt"
|
||||
#define IMX_GPT(obj) OBJECT_CHECK(IMXGPTState, (obj), TYPE_IMX_GPT)
|
||||
|
||||
typedef struct IMXGPTState{
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
ptimer_state *timer;
|
||||
MemoryRegion iomem;
|
||||
DeviceState *ccm;
|
||||
|
||||
uint32_t cr;
|
||||
uint32_t pr;
|
||||
uint32_t sr;
|
||||
uint32_t ir;
|
||||
uint32_t ocr1;
|
||||
uint32_t ocr2;
|
||||
uint32_t ocr3;
|
||||
uint32_t icr1;
|
||||
uint32_t icr2;
|
||||
uint32_t cnt;
|
||||
|
||||
uint32_t next_timeout;
|
||||
uint32_t next_int;
|
||||
|
||||
uint32_t freq;
|
||||
|
||||
qemu_irq irq;
|
||||
} IMXGPTState;
|
||||
|
||||
#endif /* IMX_GPT_H */
|
||||
@@ -1182,7 +1182,7 @@ void memory_region_init_io(MemoryRegion *mr,
|
||||
uint64_t size)
|
||||
{
|
||||
memory_region_init(mr, owner, name, size);
|
||||
mr->ops = ops;
|
||||
mr->ops = ops ? ops : &unassigned_mem_ops;
|
||||
mr->opaque = opaque;
|
||||
mr->terminates = true;
|
||||
}
|
||||
@@ -1300,14 +1300,6 @@ void memory_region_init_iommu(MemoryRegion *mr,
|
||||
notifier_list_init(&mr->iommu_notify);
|
||||
}
|
||||
|
||||
void memory_region_init_reservation(MemoryRegion *mr,
|
||||
Object *owner,
|
||||
const char *name,
|
||||
uint64_t size)
|
||||
{
|
||||
memory_region_init_io(mr, owner, &unassigned_mem_ops, mr, name, size);
|
||||
}
|
||||
|
||||
static void memory_region_finalize(Object *obj)
|
||||
{
|
||||
MemoryRegion *mr = MEMORY_REGION(obj);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user