* [Qemu-devel] [PATCH v8 00/11] i.MX: Add i.MX25 support through the 3DS evaluation board.
@ 2015-06-29 20:11 Jean-Christophe Dubois
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 01/11] i.MX: Split the i.MX serial driver into a header file and a source file Jean-Christophe Dubois
` (10 more replies)
0 siblings, 11 replies; 17+ messages in thread
From: Jean-Christophe Dubois @ 2015-06-29 20:11 UTC (permalink / raw)
To: qemu-devel; +Cc: Jean-Christophe Dubois
This series of patches add the support for the i.MX25 processor through the
Freescale 3DS evaluation board.
For now a limited set of devices are supported.
* GPT timers (from i.MX31)
* EPIT timers (from i.MX31)
* Serial ports (from i.MX31)
* Ethernet FEC port
* I2C controller
This was tested by:
* booting a minimal linux system on the i.MX25_3DS platform
* booting the Xvisor hypervisor on the i.MX25_3DS platform
* booting a minimal linux system on the KZM platform
Jean-Christophe Dubois (11):
i.MX: Split the i.MX serial driver into a haeder file and a source
file
i.MX: Split the i.MX emulator into a header file and a source file
i.MX: Split the i.MX CCM emulator into a header file and a source
file.
i.MX: Split the i.MX EPIT emulator into a header file and a source
file.
i.MX: Split the i.MX GPT emulator into a header file and a source
file.
kzm: Use modified i.MX emulators.
i.MX: Add FEC Ethernet Emulator
i.MX: Add I2C controller emulator
i.MX25: Add the i.MX25 SOC support
i.MX25: Add support for the i.MX25 PDK 3DS evaluation board
i.MX: Add qtest support for I2C device emulator.
default-configs/arm-softmmu.mak | 4 +
hw/arm/Makefile.objs | 1 +
hw/arm/fsl-imx25.c | 304 +++++++++++++++++
hw/arm/imx25_3ds.c | 217 ++++++++++++
hw/arm/kzm.c | 86 ++---
hw/char/imx_serial.c | 176 +++-------
hw/i2c/Makefile.objs | 1 +
hw/i2c/imx_i2c.c | 339 +++++++++++++++++++
hw/intc/imx_avic.c | 56 +--
hw/misc/imx_ccm.c | 75 +---
hw/net/Makefile.objs | 1 +
hw/net/imx_fec.c | 733 ++++++++++++++++++++++++++++++++++++++++
hw/timer/imx_epit.c | 65 +---
hw/timer/imx_gpt.c | 86 +----
include/hw/arm/fsl-imx25.h | 52 +++
include/hw/arm/imx.h | 34 --
include/hw/char/imx_serial.h | 104 ++++++
include/hw/i2c/imx_i2c.h | 85 +++++
include/hw/intc/imx_avic.h | 56 +++
include/hw/misc/imx_ccm.h | 91 +++++
include/hw/net/imx_fec.h | 115 +++++++
include/hw/timer/imx_epit.h | 83 +++++
include/hw/timer/imx_gpt.h | 111 ++++++
tests/Makefile | 3 +
tests/ds1338-test.c | 75 ++++
tests/libqos/i2c-imx.c | 209 ++++++++++++
tests/libqos/i2c.h | 3 +
27 files changed, 2707 insertions(+), 458 deletions(-)
create mode 100644 hw/arm/fsl-imx25.c
create mode 100644 hw/arm/imx25_3ds.c
create mode 100644 hw/i2c/imx_i2c.c
create mode 100644 hw/net/imx_fec.c
create mode 100644 include/hw/arm/fsl-imx25.h
delete mode 100644 include/hw/arm/imx.h
create mode 100644 include/hw/char/imx_serial.h
create mode 100644 include/hw/i2c/imx_i2c.h
create mode 100644 include/hw/intc/imx_avic.h
create mode 100644 include/hw/misc/imx_ccm.h
create mode 100644 include/hw/net/imx_fec.h
create mode 100644 include/hw/timer/imx_epit.h
create mode 100644 include/hw/timer/imx_gpt.h
create mode 100644 tests/ds1338-test.c
create mode 100644 tests/libqos/i2c-imx.c
--
2.1.4
^ permalink raw reply [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v8 01/11] i.MX: Split the i.MX serial driver into a header file and a source file
2015-06-29 20:11 [Qemu-devel] [PATCH v8 00/11] i.MX: Add i.MX25 support through the 3DS evaluation board Jean-Christophe Dubois
@ 2015-06-29 20:11 ` Jean-Christophe Dubois
2015-06-30 7:04 ` Peter Crosthwaite
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 02/11] i.MX: Split the i.MX AVIC emulator " Jean-Christophe Dubois
` (9 subsequent siblings)
10 siblings, 1 reply; 17+ messages in thread
From: Jean-Christophe Dubois @ 2015-06-29 20:11 UTC (permalink / raw)
To: qemu-devel; +Cc: Jean-Christophe Dubois
Also adding a "realise" callback.
This is to prepare to accomodate the SOC requirements.
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
---
Changes since v1:
* not present on v1
Changes since v2:
* not present on v2
Changes since v3:
* not present on v3
Changes since v4:
* not present on v4
Changes since v5:
* not present on v5
Changes since v6:
* not present on v6
Changes since v7:
* Splited the i.MX serial emulator into a header file and a source file
hw/char/imx_serial.c | 176 +++++++++++--------------------------------
include/hw/char/imx_serial.h | 104 +++++++++++++++++++++++++
2 files changed, 149 insertions(+), 131 deletions(-)
create mode 100644 include/hw/char/imx_serial.h
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index f3fbc77..8c2d071 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -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,16 +18,14 @@
* 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"
//#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 +37,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 +61,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;
@@ -242,13 +163,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;
@@ -298,25 +219,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 +265,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);
}
}
@@ -377,22 +298,18 @@ static void imx_event(void *opaque, int event)
}
}
-
static const struct MemoryRegionOps imx_serial_ops = {
.read = imx_serial_read,
.write = imx_serial_write,
.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);
+ /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
+ s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
@@ -401,45 +318,42 @@ 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)
{
DeviceState *dev;
SysBusDevice *bus;
- CharDriverState *chr;
- const char chr_name[] = "serial";
- char label[ARRAY_SIZE(chr_name) + 1];
-
- dev = qdev_create(NULL, TYPE_IMX_SERIAL);
if (uart >= MAX_SERIAL_PORTS) {
hw_error("Cannot assign uart %d: QEMU supports only %d ports\n",
uart, MAX_SERIAL_PORTS);
}
- chr = serial_hds[uart];
- if (!chr) {
- snprintf(label, ARRAY_SIZE(label), "%s%d", chr_name, uart);
- chr = qemu_chr_new(label, "null", NULL);
- if (!(chr)) {
- hw_error("Can't assign serial port to imx-uart%d.\n", uart);
- }
- }
- qdev_prop_set_chr(dev, "chardev", chr);
+ dev = qdev_create(NULL, TYPE_IMX_SERIAL);
+
bus = SYS_BUS_DEVICE(dev);
qdev_init_nofail(dev);
+
if (addr != (hwaddr)-1) {
sysbus_mmio_map(bus, 0, addr);
}
- sysbus_connect_irq(bus, 0, irq);
+ sysbus_connect_irq(bus, 0, irq);
}
-
-static Property imx32_serial_properties[] = {
+static Property imx_serial_properties[] = {
DEFINE_PROP_CHR("chardev", IMXSerialState, chr),
DEFINE_PROP_END_OF_LIST(),
};
@@ -447,21 +361,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;
+ set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
}
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)
diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
new file mode 100644
index 0000000..dba0cbb
--- /dev/null
+++ b/include/hw/char/imx_serial.h
@@ -0,0 +1,104 @@
+/*
+ * 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;
+
+void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq);
+
+#endif
--
2.1.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v8 02/11] i.MX: Split the i.MX AVIC emulator into a header file and a source file
2015-06-29 20:11 [Qemu-devel] [PATCH v8 00/11] i.MX: Add i.MX25 support through the 3DS evaluation board Jean-Christophe Dubois
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 01/11] i.MX: Split the i.MX serial driver into a header file and a source file Jean-Christophe Dubois
@ 2015-06-29 20:11 ` Jean-Christophe Dubois
2015-06-30 7:05 ` Peter Crosthwaite
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 03/11] i.MX: Split the i.MX CCM " Jean-Christophe Dubois
` (8 subsequent siblings)
10 siblings, 1 reply; 17+ messages in thread
From: Jean-Christophe Dubois @ 2015-06-29 20:11 UTC (permalink / raw)
To: qemu-devel; +Cc: Jean-Christophe Dubois
This is to prepare to accomodate the SOC requirements.
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
---
Changes since v1:
* not present on v1
Changes since v2:
* not present on v2
Changes since v3:
* not present on v3
Changes since v4:
* not present on v4
Changes since v5:
* not present on v5
Changes since v6:
* not present on v6
Changes since v7:
* Splited the i.MX AVIC emulator into a header file and a source file
hw/intc/imx_avic.c | 56 +++++++++-------------------------------------
include/hw/intc/imx_avic.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 66 insertions(+), 46 deletions(-)
create mode 100644 include/hw/intc/imx_avic.h
diff --git a/hw/intc/imx_avic.c b/hw/intc/imx_avic.c
index e48f66c..96c376b 100644
--- a/hw/intc/imx_avic.c
+++ b/hw/intc/imx_avic.c
@@ -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);
diff --git a/include/hw/intc/imx_avic.h b/include/hw/intc/imx_avic.h
new file mode 100644
index 0000000..1645ba6
--- /dev/null
+++ b/include/hw/intc/imx_avic.h
@@ -0,0 +1,56 @@
+/*
+ * 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 {
+ /*< 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
--
2.1.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v8 03/11] i.MX: Split the i.MX CCM emulator into a header file and a source file.
2015-06-29 20:11 [Qemu-devel] [PATCH v8 00/11] i.MX: Add i.MX25 support through the 3DS evaluation board Jean-Christophe Dubois
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 01/11] i.MX: Split the i.MX serial driver into a header file and a source file Jean-Christophe Dubois
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 02/11] i.MX: Split the i.MX AVIC emulator " Jean-Christophe Dubois
@ 2015-06-29 20:11 ` Jean-Christophe Dubois
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 04/11] i.MX: Split the i.MX EPIT " Jean-Christophe Dubois
` (7 subsequent siblings)
10 siblings, 0 replies; 17+ messages in thread
From: Jean-Christophe Dubois @ 2015-06-29 20:11 UTC (permalink / raw)
To: qemu-devel; +Cc: Jean-Christophe Dubois
This is to prepare to accomodate the SOC requirements.
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
---
Changes since v1:
* not present on v1
Changes since v2:
* not present on v2
Changes since v3:
* not present on v3
Changes since v4:
* not present on v4
Changes since v5:
* not present on v5
Changes since v6:
* not present on v6
Changes since v7:
* Splited the i.MX CCM emulator into a header file and a source file
hw/misc/imx_ccm.c | 75 +++-----------------------------------
include/hw/misc/imx_ccm.h | 91 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 96 insertions(+), 70 deletions(-)
create mode 100644 include/hw/misc/imx_ccm.h
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
index 0920288..c213282 100644
--- a/hw/misc/imx_ccm.c
+++ b/hw/misc/imx_ccm.c
@@ -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);
@@ -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;
diff --git a/include/hw/misc/imx_ccm.h b/include/hw/misc/imx_ccm.h
new file mode 100644
index 0000000..7febafd
--- /dev/null
+++ b/include/hw/misc/imx_ccm.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 {
+ /* <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 */
--
2.1.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v8 04/11] i.MX: Split the i.MX EPIT emulator into a header file and a source file.
2015-06-29 20:11 [Qemu-devel] [PATCH v8 00/11] i.MX: Add i.MX25 support through the 3DS evaluation board Jean-Christophe Dubois
` (2 preceding siblings ...)
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 03/11] i.MX: Split the i.MX CCM " Jean-Christophe Dubois
@ 2015-06-29 20:11 ` Jean-Christophe Dubois
2015-06-30 7:12 ` Peter Crosthwaite
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 05/11] i.MX: Split the i.MX GPT " Jean-Christophe Dubois
` (6 subsequent siblings)
10 siblings, 1 reply; 17+ messages in thread
From: Jean-Christophe Dubois @ 2015-06-29 20:11 UTC (permalink / raw)
To: qemu-devel; +Cc: Jean-Christophe Dubois
This is to prepare to accomodate the SOC requirements.
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
---
Changes since v1:
* not present on v1
Changes since v2:
* not present on v2
Changes since v3:
* not present on v3
Changes since v4:
* not present on v4
Changes since v5:
* not present on v5
Changes since v6:
* not present on v6
Changes since v7:
* Splited the i.MX EPIT emulator into a header file and a source file
hw/timer/imx_epit.c | 65 +++++------------------------------
include/hw/timer/imx_epit.h | 83 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 92 insertions(+), 56 deletions(-)
create mode 100644 include/hw/timer/imx_epit.h
diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
index ffefc22..39fc3f1 100644
--- a/hw/timer/imx_epit.c
+++ b/hw/timer/imx_epit.c
@@ -5,23 +5,17 @@
* 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 +55,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 +66,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 +127,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 +297,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[]) {
diff --git a/include/hw/timer/imx_epit.h b/include/hw/timer/imx_epit.h
new file mode 100644
index 0000000..dbc99ca
--- /dev/null
+++ b/include/hw/timer/imx_epit.h
@@ -0,0 +1,83 @@
+/*
+ * 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 {
+ /* <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;
+
+void imx_timerp_create(const hwaddr addr,
+ qemu_irq irq,
+ DeviceState *ccm);
+
+#endif /* IMX_EPIT_H */
--
2.1.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v8 05/11] i.MX: Split the i.MX GPT emulator into a header file and a source file.
2015-06-29 20:11 [Qemu-devel] [PATCH v8 00/11] i.MX: Add i.MX25 support through the 3DS evaluation board Jean-Christophe Dubois
` (3 preceding siblings ...)
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 04/11] i.MX: Split the i.MX EPIT " Jean-Christophe Dubois
@ 2015-06-29 20:12 ` Jean-Christophe Dubois
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 06/11] kzm: Use modified i.MX emulators Jean-Christophe Dubois
` (5 subsequent siblings)
10 siblings, 0 replies; 17+ messages in thread
From: Jean-Christophe Dubois @ 2015-06-29 20:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Jean-Christophe Dubois
This is to prepare to accomodate the SOC requirements.
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
---
Changes since v1:
* not present on v1
Changes since v2:
* not present on v2
Changes since v3:
* not present on v3
Changes since v4:
* not present on v4
Changes since v5:
* not present on v5
Changes since v6:
* not present on v6
Changes since v7:
* Splited the i.MX GPT emulator into a header file and a source file
hw/timer/imx_gpt.c | 86 +++--------------------------------
include/hw/timer/imx_gpt.h | 111 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 117 insertions(+), 80 deletions(-)
create mode 100644 include/hw/timer/imx_gpt.h
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index 3b31010..90682e0 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -5,23 +5,17 @@
* 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 +68,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 +106,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 +133,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;
diff --git a/include/hw/timer/imx_gpt.h b/include/hw/timer/imx_gpt.h
new file mode 100644
index 0000000..8342c86
--- /dev/null
+++ b/include/hw/timer/imx_gpt.h
@@ -0,0 +1,111 @@
+/*
+ * 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 {
+ /* <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;
+
+void imx_timerg_create(const hwaddr addr,
+ qemu_irq irq,
+ DeviceState *ccm);
+
+#endif /* IMX_GPT_H */
--
2.1.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v8 06/11] kzm: Use modified i.MX emulators.
2015-06-29 20:11 [Qemu-devel] [PATCH v8 00/11] i.MX: Add i.MX25 support through the 3DS evaluation board Jean-Christophe Dubois
` (4 preceding siblings ...)
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 05/11] i.MX: Split the i.MX GPT " Jean-Christophe Dubois
@ 2015-06-29 20:12 ` Jean-Christophe Dubois
2015-06-30 7:12 ` Peter Crosthwaite
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 07/11] i.MX: Add FEC Ethernet Emulator Jean-Christophe Dubois
` (4 subsequent siblings)
10 siblings, 1 reply; 17+ messages in thread
From: Jean-Christophe Dubois @ 2015-06-29 20:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Jean-Christophe Dubois
Use modified AVIC, CCM, UART, GPT, EPIT emultors.
Tested by booting Linux one KZM emulator.
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
---
Changes since v1:
* not present on v1
Changes since v2:
* not present on v2
Changes since v3:
* not present on v3
Changes since v4:
* not present on v4
Changes since v5:
* not present on v5
Changes since v6:
* not present on v6
Changes since v7:
* update KZM target to use new emulators
hw/arm/kzm.c | 86 +++++++++++++++++++++++++++-------------------------
include/hw/arm/imx.h | 34 ---------------------
2 files changed, 45 insertions(+), 75 deletions(-)
delete mode 100644 include/hw/arm/imx.h
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
index 5be0369..485e745 100644
--- a/hw/arm/kzm.c
+++ b/hw/arm/kzm.c
@@ -22,45 +22,49 @@
#include "sysemu/sysemu.h"
#include "hw/boards.h"
#include "hw/char/serial.h"
-#include "hw/arm/imx.h"
-
- /* Memory map for Kzm Emulation Baseboard:
- * 0x00000000-0x00003fff 16k secure ROM IGNORED
- * 0x00004000-0x00407fff Reserved IGNORED
- * 0x00404000-0x00407fff ROM IGNORED
- * 0x00408000-0x0fffffff Reserved IGNORED
- * 0x10000000-0x1fffbfff RAM aliasing IGNORED
- * 0x1fffc000-0x1fffffff RAM EMULATED
- * 0x20000000-0x2fffffff Reserved IGNORED
- * 0x30000000-0x7fffffff I.MX31 Internal Register Space
- * 0x43f00000 IO_AREA0
- * 0x43f90000 UART1 EMULATED
- * 0x43f94000 UART2 EMULATED
- * 0x68000000 AVIC EMULATED
- * 0x53f80000 CCM EMULATED
- * 0x53f94000 PIT 1 EMULATED
- * 0x53f98000 PIT 2 EMULATED
- * 0x53f90000 GPT EMULATED
- * 0x80000000-0x87ffffff RAM EMULATED
- * 0x88000000-0x8fffffff RAM Aliasing EMULATED
- * 0xa0000000-0xafffffff NAND Flash IGNORED
- * 0xb0000000-0xb3ffffff Unavailable IGNORED
- * 0xb4000000-0xb4000fff 8-bit free space IGNORED
- * 0xb4001000-0xb400100f Board control IGNORED
- * 0xb4001003 DIP switch
- * 0xb4001010-0xb400101f 7-segment LED IGNORED
- * 0xb4001020-0xb400102f LED IGNORED
- * 0xb4001030-0xb400103f LED IGNORED
- * 0xb4001040-0xb400104f FPGA, UART EMULATED
- * 0xb4001050-0xb400105f FPGA, UART EMULATED
- * 0xb4001060-0xb40fffff FPGA IGNORED
- * 0xb6000000-0xb61fffff LAN controller EMULATED
- * 0xb6200000-0xb62fffff FPGA NAND Controller IGNORED
- * 0xb6300000-0xb7ffffff Free IGNORED
- * 0xb8000000-0xb8004fff Memory control registers IGNORED
- * 0xc0000000-0xc3ffffff PCMCIA/CF IGNORED
- * 0xc4000000-0xffffffff Reserved IGNORED
- */
+#include "hw/misc/imx_ccm.h"
+#include "hw/intc/imx_avic.h"
+#include "hw/timer/imx_epit.h"
+#include "hw/timer/imx_gpt.h"
+#include "hw/char/imx_serial.h"
+
+/* Memory map for Kzm Emulation Baseboard:
+ * 0x00000000-0x00003fff 16k secure ROM IGNORED
+ * 0x00004000-0x00407fff Reserved IGNORED
+ * 0x00404000-0x00407fff ROM IGNORED
+ * 0x00408000-0x0fffffff Reserved IGNORED
+ * 0x10000000-0x1fffbfff RAM aliasing IGNORED
+ * 0x1fffc000-0x1fffffff RAM EMULATED
+ * 0x20000000-0x2fffffff Reserved IGNORED
+ * 0x30000000-0x7fffffff I.MX31 Internal Register Space
+ * 0x43f00000 IO_AREA0
+ * 0x43f90000 UART1 EMULATED
+ * 0x43f94000 UART2 EMULATED
+ * 0x68000000 AVIC EMULATED
+ * 0x53f80000 CCM EMULATED
+ * 0x53f94000 PIT 1 EMULATED
+ * 0x53f98000 PIT 2 EMULATED
+ * 0x53f90000 GPT EMULATED
+ * 0x80000000-0x87ffffff RAM EMULATED
+ * 0x88000000-0x8fffffff RAM Aliasing EMULATED
+ * 0xa0000000-0xafffffff NAND Flash IGNORED
+ * 0xb0000000-0xb3ffffff Unavailable IGNORED
+ * 0xb4000000-0xb4000fff 8-bit free space IGNORED
+ * 0xb4001000-0xb400100f Board control IGNORED
+ * 0xb4001003 DIP switch
+ * 0xb4001010-0xb400101f 7-segment LED IGNORED
+ * 0xb4001020-0xb400102f LED IGNORED
+ * 0xb4001030-0xb400103f LED IGNORED
+ * 0xb4001040-0xb400104f FPGA, UART EMULATED
+ * 0xb4001050-0xb400105f FPGA, UART EMULATED
+ * 0xb4001060-0xb40fffff FPGA IGNORED
+ * 0xb6000000-0xb61fffff LAN controller EMULATED
+ * 0xb6200000-0xb62fffff FPGA NAND Controller IGNORED
+ * 0xb6300000-0xb7ffffff Free IGNORED
+ * 0xb8000000-0xb8004fff Memory control registers IGNORED
+ * 0xc0000000-0xc3ffffff PCMCIA/CF IGNORED
+ * 0xc4000000-0xffffffff Reserved IGNORED
+ */
#define KZM_RAMADDRESS (0x80000000)
#define KZM_FPGA (0xb4001040)
@@ -106,7 +110,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 +118,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);
diff --git a/include/hw/arm/imx.h b/include/hw/arm/imx.h
deleted file mode 100644
index ea9e093..0000000
--- a/include/hw/arm/imx.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * i.MX31 emulation
- *
- * Copyright (C) 2012 Peter Chubb
- * NICTA
- *
- * This code is released under the GPL, version 2.0 or later
- * See the file `../COPYING' for details.
- */
-
-#ifndef IMX_H
-#define IMX_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);
-void imx_timerg_create(const hwaddr addr,
- qemu_irq irq,
- DeviceState *ccm);
-
-
-#endif /* IMX_H */
--
2.1.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v8 07/11] i.MX: Add FEC Ethernet Emulator
2015-06-29 20:11 [Qemu-devel] [PATCH v8 00/11] i.MX: Add i.MX25 support through the 3DS evaluation board Jean-Christophe Dubois
` (5 preceding siblings ...)
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 06/11] kzm: Use modified i.MX emulators Jean-Christophe Dubois
@ 2015-06-29 20:12 ` Jean-Christophe Dubois
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 08/11] i.MX: Add I2C controller emulator Jean-Christophe Dubois
` (3 subsequent siblings)
10 siblings, 0 replies; 17+ messages in thread
From: Jean-Christophe Dubois @ 2015-06-29 20:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Jean-Christophe Dubois
This is based on mcf_fec.c FEC implementation for Coldfire
* A generic PHY was added (borrowwed from LAN9118)
* The buffer management is also modified as buffers are
slightly different between Coldfire and i.MX
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
Changes since v1:
* none
Changes since v2:
* use QOM cast
* reworked debug printf
* use CamelCase for state type
* warn with qemu_log_mask(LOG_GUEST_ERROR) or qemu_log_mask(LOG_UNIMP)
* move to dma_memory_read/write API
* rework interrupt handling
* use qemu_flush_queued_packets() in rx_enable()
Changes since v3:
* use realise for device initialization
* More QOM cast
* reworked debug printf some more
* standardise GPL header
* use CamelCase for buffer descriptor type
Changes since v4:
* none
Changes since v5:
* replace hw_error() with qemu_log_mask(LOG_GUEST_ERROR, ...)
* remove reformating of imx.h header file.
* remove unnecessary spaces.
Changes since v6:
* port to new memory API
Change since v7:
* refactor emulator to be used by SOC
default-configs/arm-softmmu.mak | 1 +
hw/net/Makefile.objs | 1 +
hw/net/imx_fec.c | 733 ++++++++++++++++++++++++++++++++++++++++
include/hw/net/imx_fec.h | 115 +++++++
4 files changed, 850 insertions(+)
create mode 100644 hw/net/imx_fec.c
create mode 100644 include/hw/net/imx_fec.h
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 74f1db3..d21ff7b 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -28,6 +28,7 @@ CONFIG_SSI_M25P80=y
CONFIG_LAN9118=y
CONFIG_SMC91C111=y
CONFIG_ALLWINNER_EMAC=y
+CONFIG_IMX_FEC=y
CONFIG_DS1338=y
CONFIG_PFLASH_CFI01=y
CONFIG_PFLASH_CFI02=y
diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
index 9880173..64d0449 100644
--- a/hw/net/Makefile.objs
+++ b/hw/net/Makefile.objs
@@ -19,6 +19,7 @@ common-obj-$(CONFIG_XGMAC) += xgmac.o
common-obj-$(CONFIG_MIPSNET) += mipsnet.o
common-obj-$(CONFIG_XILINX_AXI) += xilinx_axienet.o
common-obj-$(CONFIG_ALLWINNER_EMAC) += allwinner_emac.o
+common-obj-$(CONFIG_IMX_FEC) += imx_fec.o
common-obj-$(CONFIG_CADENCE) += cadence_gem.o
common-obj-$(CONFIG_STELLARIS_ENET) += stellaris_enet.o
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
new file mode 100644
index 0000000..05e0f45
--- /dev/null
+++ b/hw/net/imx_fec.c
@@ -0,0 +1,733 @@
+/*
+ * i.MX Fast Ethernet Controller emulation.
+ *
+ * Copyright (c) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
+ *
+ * Based on Coldfire Fast Ethernet Controller emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * 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/>.
+ */
+
+#include "hw/net/imx_fec.h"
+#include "sysemu/dma.h"
+
+/* For crc32 */
+#include <zlib.h>
+
+#ifndef IMX_FEC_DEBUG
+#define IMX_FEC_DEBUG 0
+#endif
+
+#ifndef IMX_PHY_DEBUG
+#define IMX_PHY_DEBUG 0
+#endif
+
+#if IMX_FEC_DEBUG
+#define FEC_PRINTF(fmt, ...) \
+ do { fprintf(stderr, "%s[%s]: " fmt , TYPE_IMX_FEC, __func__, \
+ ## __VA_ARGS__); \
+ } while (0)
+#else
+#define FEC_PRINTF(fmt, ...) do {} while (0)
+#endif
+
+#if IMX_PHY_DEBUG
+#define PHY_PRINTF(fmt, ...) \
+ do { fprintf(stderr, "%s.phy[%s]: " fmt , TYPE_IMX_FEC, __func__, \
+ ## __VA_ARGS__); \
+ } while (0)
+#else
+#define PHY_PRINTF(fmt, ...) do {} while (0)
+#endif
+
+static const VMStateDescription vmstate_imx_fec = {
+ .name = TYPE_IMX_FEC,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(irq_state, IMXFECState),
+ VMSTATE_UINT32(eir, IMXFECState),
+ VMSTATE_UINT32(eimr, IMXFECState),
+ VMSTATE_UINT32(rx_enabled, IMXFECState),
+ VMSTATE_UINT32(rx_descriptor, IMXFECState),
+ VMSTATE_UINT32(tx_descriptor, IMXFECState),
+ VMSTATE_UINT32(ecr, IMXFECState),
+ VMSTATE_UINT32(mmfr, IMXFECState),
+ VMSTATE_UINT32(mscr, IMXFECState),
+ VMSTATE_UINT32(mibc, IMXFECState),
+ VMSTATE_UINT32(rcr, IMXFECState),
+ VMSTATE_UINT32(tcr, IMXFECState),
+ VMSTATE_UINT32(tfwr, IMXFECState),
+ VMSTATE_UINT32(frsr, IMXFECState),
+ VMSTATE_UINT32(erdsr, IMXFECState),
+ VMSTATE_UINT32(etdsr, IMXFECState),
+ VMSTATE_UINT32(emrbr, IMXFECState),
+ VMSTATE_UINT32(miigsk_cfgr, IMXFECState),
+ VMSTATE_UINT32(miigsk_enr, IMXFECState),
+
+ VMSTATE_UINT32(phy_status, IMXFECState),
+ VMSTATE_UINT32(phy_control, IMXFECState),
+ VMSTATE_UINT32(phy_advertise, IMXFECState),
+ VMSTATE_UINT32(phy_int, IMXFECState),
+ VMSTATE_UINT32(phy_int_mask, IMXFECState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+#define PHY_INT_ENERGYON (1 << 7)
+#define PHY_INT_AUTONEG_COMPLETE (1 << 6)
+#define PHY_INT_FAULT (1 << 5)
+#define PHY_INT_DOWN (1 << 4)
+#define PHY_INT_AUTONEG_LP (1 << 3)
+#define PHY_INT_PARFAULT (1 << 2)
+#define PHY_INT_AUTONEG_PAGE (1 << 1)
+
+static void imx_fec_update(IMXFECState *s);
+
+/*
+ * The MII phy could raise a GPIO to the processor which in turn
+ * could be handled as an interrpt by the OS.
+ * For now we don't handle any GPIO/interrupt line, so the OS will
+ * have to poll for the PHY status.
+ */
+static void phy_update_irq(IMXFECState *s)
+{
+ imx_fec_update(s);
+}
+
+static void phy_update_link(IMXFECState *s)
+{
+ /* Autonegotiation status mirrors link status. */
+ if (qemu_get_queue(s->nic)->link_down) {
+ PHY_PRINTF("link is down\n");
+ s->phy_status &= ~0x0024;
+ s->phy_int |= PHY_INT_DOWN;
+ } else {
+ PHY_PRINTF("link is up\n");
+ s->phy_status |= 0x0024;
+ s->phy_int |= PHY_INT_ENERGYON;
+ s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
+ }
+ phy_update_irq(s);
+}
+
+static void imx_fec_set_link(NetClientState *nc)
+{
+ phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
+}
+
+static void phy_reset(IMXFECState *s)
+{
+ s->phy_status = 0x7809;
+ s->phy_control = 0x3000;
+ s->phy_advertise = 0x01e1;
+ s->phy_int_mask = 0;
+ s->phy_int = 0;
+ phy_update_link(s);
+}
+
+static uint32_t do_phy_read(IMXFECState *s, int reg)
+{
+ uint32_t val;
+
+ if (reg > 31) {
+ /* we only advertise one phy */
+ return 0;
+ }
+
+ switch (reg) {
+ case 0: /* Basic Control */
+ val = s->phy_control;
+ break;
+ case 1: /* Basic Status */
+ val = s->phy_status;
+ break;
+ case 2: /* ID1 */
+ val = 0x0007;
+ break;
+ case 3: /* ID2 */
+ val = 0xc0d1;
+ break;
+ case 4: /* Auto-neg advertisement */
+ val = s->phy_advertise;
+ break;
+ case 5: /* Auto-neg Link Partner Ability */
+ val = 0x0f71;
+ break;
+ case 6: /* Auto-neg Expansion */
+ val = 1;
+ break;
+ case 29: /* Interrupt source. */
+ val = s->phy_int;
+ s->phy_int = 0;
+ phy_update_irq(s);
+ break;
+ case 30: /* Interrupt mask */
+ val = s->phy_int_mask;
+ break;
+ case 17:
+ case 18:
+ case 27:
+ case 31:
+ qemu_log_mask(LOG_UNIMP, "%s.phy[%s]: reg %d not implemented\n",
+ TYPE_IMX_FEC, __func__, reg);
+ val = 0;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
+ TYPE_IMX_FEC, __func__, reg);
+ val = 0;
+ break;
+ }
+
+ PHY_PRINTF("read 0x%04x @ %d\n", val, reg);
+
+ return val;
+}
+
+static void do_phy_write(IMXFECState *s, int reg, uint32_t val)
+{
+ PHY_PRINTF("write 0x%04x @ %d\n", val, reg);
+
+ if (reg > 31) {
+ /* we only advertise one phy */
+ return;
+ }
+
+ switch (reg) {
+ case 0: /* Basic Control */
+ if (val & 0x8000) {
+ phy_reset(s);
+ } else {
+ s->phy_control = val & 0x7980;
+ /* Complete autonegotiation immediately. */
+ if (val & 0x1000) {
+ s->phy_status |= 0x0020;
+ }
+ }
+ break;
+ case 4: /* Auto-neg advertisement */
+ s->phy_advertise = (val & 0x2d7f) | 0x80;
+ break;
+ case 30: /* Interrupt mask */
+ s->phy_int_mask = val & 0xff;
+ phy_update_irq(s);
+ break;
+ case 17:
+ case 18:
+ case 27:
+ case 31:
+ qemu_log_mask(LOG_UNIMP, "%s.phy[%s]: reg %d not implemented\n",
+ TYPE_IMX_FEC, __func__, reg);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s.phy[%s]: Bad address at offset %d\n",
+ TYPE_IMX_FEC, __func__, reg);
+ break;
+ }
+}
+
+static void imx_fec_read_bd(IMXFECBufDesc *bd, dma_addr_t addr)
+{
+ dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd));
+}
+
+static void imx_fec_write_bd(IMXFECBufDesc *bd, dma_addr_t addr)
+{
+ dma_memory_write(&address_space_memory, addr, bd, sizeof(*bd));
+}
+
+static void imx_fec_update(IMXFECState *s)
+{
+ uint32_t active;
+ uint32_t changed;
+
+ active = s->eir & s->eimr;
+ changed = active ^ s->irq_state;
+ if (changed) {
+ qemu_set_irq(s->irq, active);
+ }
+ s->irq_state = active;
+}
+
+static void imx_fec_do_tx(IMXFECState *s)
+{
+ int frame_size = 0;
+ uint8_t frame[FEC_MAX_FRAME_SIZE];
+ uint8_t *ptr = frame;
+ uint32_t addr = s->tx_descriptor;
+
+ while (1) {
+ IMXFECBufDesc bd;
+ int len;
+
+ imx_fec_read_bd(&bd, addr);
+ FEC_PRINTF("tx_bd %x flags %04x len %d data %08x\n",
+ addr, bd.flags, bd.length, bd.data);
+ if ((bd.flags & FEC_BD_R) == 0) {
+ /* Run out of descriptors to transmit. */
+ break;
+ }
+ len = bd.length;
+ if (frame_size + len > FEC_MAX_FRAME_SIZE) {
+ len = FEC_MAX_FRAME_SIZE - frame_size;
+ s->eir |= FEC_INT_BABT;
+ }
+ dma_memory_read(&address_space_memory, bd.data, ptr, len);
+ ptr += len;
+ frame_size += len;
+ if (bd.flags & FEC_BD_L) {
+ /* Last buffer in frame. */
+ qemu_send_packet(qemu_get_queue(s->nic), frame, len);
+ ptr = frame;
+ frame_size = 0;
+ s->eir |= FEC_INT_TXF;
+ }
+ s->eir |= FEC_INT_TXB;
+ bd.flags &= ~FEC_BD_R;
+ /* Write back the modified descriptor. */
+ imx_fec_write_bd(&bd, addr);
+ /* Advance to the next descriptor. */
+ if ((bd.flags & FEC_BD_W) != 0) {
+ addr = s->etdsr;
+ } else {
+ addr += 8;
+ }
+ }
+
+ s->tx_descriptor = addr;
+
+ imx_fec_update(s);
+}
+
+static void imx_fec_enable_rx(IMXFECState *s)
+{
+ IMXFECBufDesc bd;
+ uint32_t tmp;
+
+ imx_fec_read_bd(&bd, s->rx_descriptor);
+
+ tmp = ((bd.flags & FEC_BD_E) != 0);
+
+ if (!tmp) {
+ FEC_PRINTF("RX buffer full\n");
+ } else if (!s->rx_enabled) {
+ qemu_flush_queued_packets(qemu_get_queue(s->nic));
+ }
+
+ s->rx_enabled = tmp;
+}
+
+static void imx_fec_reset(DeviceState *d)
+{
+ IMXFECState *s = IMX_FEC(d);
+
+ /* Reset the FEC */
+ s->eir = 0;
+ s->eimr = 0;
+ s->rx_enabled = 0;
+ s->ecr = 0;
+ s->mscr = 0;
+ s->mibc = 0xc0000000;
+ s->rcr = 0x05ee0001;
+ s->tcr = 0;
+ s->tfwr = 0;
+ s->frsr = 0x500;
+ s->miigsk_cfgr = 0;
+ s->miigsk_enr = 0x6;
+
+ /* We also reset the PHY */
+ phy_reset(s);
+}
+
+static uint64_t imx_fec_read(void *opaque, hwaddr addr, unsigned size)
+{
+ IMXFECState *s = IMX_FEC(opaque);
+
+ FEC_PRINTF("reading from @ 0x%03x\n", (int)addr);
+
+ switch (addr & 0x3ff) {
+ case 0x004:
+ return s->eir;
+ case 0x008:
+ return s->eimr;
+ case 0x010:
+ return s->rx_enabled ? (1 << 24) : 0; /* RDAR */
+ case 0x014:
+ return 0; /* TDAR */
+ case 0x024:
+ return s->ecr;
+ case 0x040:
+ return s->mmfr;
+ case 0x044:
+ return s->mscr;
+ case 0x064:
+ return s->mibc; /* MIBC */
+ case 0x084:
+ return s->rcr;
+ case 0x0c4:
+ return s->tcr;
+ case 0x0e4: /* PALR */
+ return (s->conf.macaddr.a[0] << 24)
+ | (s->conf.macaddr.a[1] << 16)
+ | (s->conf.macaddr.a[2] << 8)
+ | s->conf.macaddr.a[3];
+ break;
+ case 0x0e8: /* PAUR */
+ return (s->conf.macaddr.a[4] << 24)
+ | (s->conf.macaddr.a[5] << 16)
+ | 0x8808;
+ case 0x0ec:
+ return 0x10000; /* OPD */
+ case 0x118:
+ return 0;
+ case 0x11c:
+ return 0;
+ case 0x120:
+ return 0;
+ case 0x124:
+ return 0;
+ case 0x144:
+ return s->tfwr;
+ case 0x14c:
+ return 0x600;
+ case 0x150:
+ return s->frsr;
+ case 0x180:
+ return s->erdsr;
+ case 0x184:
+ return s->etdsr;
+ case 0x188:
+ return s->emrbr;
+ case 0x300:
+ return s->miigsk_cfgr;
+ case 0x308:
+ return s->miigsk_enr;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
+ TYPE_IMX_FEC, __func__, (int)addr);
+ return 0;
+ }
+}
+
+static void imx_fec_write(void *opaque, hwaddr addr,
+ uint64_t value, unsigned size)
+{
+ IMXFECState *s = IMX_FEC(opaque);
+
+ FEC_PRINTF("writing 0x%08x @ 0x%03x\n", (int)value, (int)addr);
+
+ switch (addr & 0x3ff) {
+ case 0x004: /* EIR */
+ s->eir &= ~value;
+ break;
+ case 0x008: /* EIMR */
+ s->eimr = value;
+ break;
+ case 0x010: /* RDAR */
+ if ((s->ecr & FEC_EN) && !s->rx_enabled) {
+ imx_fec_enable_rx(s);
+ }
+ break;
+ case 0x014: /* TDAR */
+ if (s->ecr & FEC_EN) {
+ imx_fec_do_tx(s);
+ }
+ break;
+ case 0x024: /* ECR */
+ s->ecr = value;
+ if (value & FEC_RESET) {
+ imx_fec_reset(DEVICE(s));
+ }
+ if ((s->ecr & FEC_EN) == 0) {
+ s->rx_enabled = 0;
+ }
+ break;
+ case 0x040: /* MMFR */
+ /* store the value */
+ s->mmfr = value;
+ if (extract32(value, 28, 1)) {
+ do_phy_write(s, extract32(value, 18, 9), extract32(value, 0, 16));
+ } else {
+ s->mmfr = do_phy_read(s, extract32(value, 18, 9));
+ }
+ /* raise the interrupt as the PHY operation is done */
+ s->eir |= FEC_INT_MII;
+ break;
+ case 0x044: /* MSCR */
+ s->mscr = value & 0xfe;
+ break;
+ case 0x064: /* MIBC */
+ /* TODO: Implement MIB. */
+ s->mibc = (value & 0x80000000) ? 0xc0000000 : 0;
+ break;
+ case 0x084: /* RCR */
+ s->rcr = value & 0x07ff003f;
+ /* TODO: Implement LOOP mode. */
+ break;
+ case 0x0c4: /* TCR */
+ /* We transmit immediately, so raise GRA immediately. */
+ s->tcr = value;
+ if (value & 1) {
+ s->eir |= FEC_INT_GRA;
+ }
+ break;
+ case 0x0e4: /* PALR */
+ s->conf.macaddr.a[0] = value >> 24;
+ s->conf.macaddr.a[1] = value >> 16;
+ s->conf.macaddr.a[2] = value >> 8;
+ s->conf.macaddr.a[3] = value;
+ break;
+ case 0x0e8: /* PAUR */
+ s->conf.macaddr.a[4] = value >> 24;
+ s->conf.macaddr.a[5] = value >> 16;
+ break;
+ case 0x0ec: /* OPDR */
+ break;
+ case 0x118: /* IAUR */
+ case 0x11c: /* IALR */
+ case 0x120: /* GAUR */
+ case 0x124: /* GALR */
+ /* TODO: implement MAC hash filtering. */
+ break;
+ case 0x144: /* TFWR */
+ s->tfwr = value & 3;
+ break;
+ case 0x14c: /* FRBR */
+ /* FRBR writes ignored. */
+ break;
+ case 0x150: /* FRSR */
+ s->frsr = (value & 0x3fc) | 0x400;
+ break;
+ case 0x180: /* ERDSR */
+ s->erdsr = value & ~3;
+ s->rx_descriptor = s->erdsr;
+ break;
+ case 0x184: /* ETDSR */
+ s->etdsr = value & ~3;
+ s->tx_descriptor = s->etdsr;
+ break;
+ case 0x188: /* EMRBR */
+ s->emrbr = value & 0x7f0;
+ break;
+ case 0x300: /* MIIGSK_CFGR */
+ s->miigsk_cfgr = value & 0x53;
+ break;
+ case 0x308: /* MIIGSK_ENR */
+ s->miigsk_enr = (value & 0x2) ? 0x6 : 0;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
+ TYPE_IMX_FEC, __func__, (int)addr);
+ break;
+ }
+
+ imx_fec_update(s);
+}
+
+static int imx_fec_can_receive(NetClientState *nc)
+{
+ IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
+
+ return s->rx_enabled;
+}
+
+static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
+ size_t len)
+{
+ IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
+ IMXFECBufDesc bd;
+ uint32_t flags = 0;
+ uint32_t addr;
+ uint32_t crc;
+ uint32_t buf_addr;
+ uint8_t *crc_ptr;
+ unsigned int buf_len;
+ size_t size = len;
+
+ FEC_PRINTF("len %d\n", (int)size);
+
+ if (!s->rx_enabled) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Unexpected packet\n",
+ TYPE_IMX_FEC, __func__);
+ return 0;
+ }
+
+ /* 4 bytes for the CRC. */
+ size += 4;
+ crc = cpu_to_be32(crc32(~0, buf, size));
+ crc_ptr = (uint8_t *) &crc;
+
+ /* Huge frames are truncted. */
+ if (size > FEC_MAX_FRAME_SIZE) {
+ size = FEC_MAX_FRAME_SIZE;
+ flags |= FEC_BD_TR | FEC_BD_LG;
+ }
+
+ /* Frames larger than the user limit just set error flags. */
+ if (size > (s->rcr >> 16)) {
+ flags |= FEC_BD_LG;
+ }
+
+ addr = s->rx_descriptor;
+ while (size > 0) {
+ imx_fec_read_bd(&bd, addr);
+ if ((bd.flags & FEC_BD_E) == 0) {
+ /* No descriptors available. Bail out. */
+ /*
+ * FIXME: This is wrong. We should probably either
+ * save the remainder for when more RX buffers are
+ * available, or flag an error.
+ */
+ qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Lost end of frame\n",
+ TYPE_IMX_FEC, __func__);
+ break;
+ }
+ buf_len = (size <= s->emrbr) ? size : s->emrbr;
+ bd.length = buf_len;
+ size -= buf_len;
+ FEC_PRINTF("rx_bd %x length %d\n", addr, bd.length);
+ /* The last 4 bytes are the CRC. */
+ if (size < 4) {
+ buf_len += size - 4;
+ }
+ buf_addr = bd.data;
+ dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
+ buf += buf_len;
+ if (size < 4) {
+ dma_memory_write(&address_space_memory, buf_addr + buf_len,
+ crc_ptr, 4 - size);
+ crc_ptr += 4 - size;
+ }
+ bd.flags &= ~FEC_BD_E;
+ if (size == 0) {
+ /* Last buffer in frame. */
+ bd.flags |= flags | FEC_BD_L;
+ FEC_PRINTF("rx frame flags %04x\n", bd.flags);
+ s->eir |= FEC_INT_RXF;
+ } else {
+ s->eir |= FEC_INT_RXB;
+ }
+ imx_fec_write_bd(&bd, addr);
+ /* Advance to the next descriptor. */
+ if ((bd.flags & FEC_BD_W) != 0) {
+ addr = s->erdsr;
+ } else {
+ addr += 8;
+ }
+ }
+ s->rx_descriptor = addr;
+ imx_fec_enable_rx(s);
+ imx_fec_update(s);
+ return len;
+}
+
+static const MemoryRegionOps imx_fec_ops = {
+ .read = imx_fec_read,
+ .write = imx_fec_write,
+ .valid.min_access_size = 4,
+ .valid.max_access_size = 4,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void imx_fec_cleanup(NetClientState *nc)
+{
+ IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
+
+ s->nic = NULL;
+}
+
+static NetClientInfo net_imx_fec_info = {
+ .type = NET_CLIENT_OPTIONS_KIND_NIC,
+ .size = sizeof(NICState),
+ .can_receive = imx_fec_can_receive,
+ .receive = imx_fec_receive,
+ .cleanup = imx_fec_cleanup,
+ .link_status_changed = imx_fec_set_link,
+};
+
+
+static void imx_fec_realize(DeviceState *dev, Error **errp)
+{
+ IMXFECState *s = IMX_FEC(dev);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(dev), &imx_fec_ops, s,
+ TYPE_IMX_FEC, 0x400);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
+ qemu_macaddr_default_if_unset(&s->conf.macaddr);
+
+ s->conf.peers.ncs[0] = nd_table[0].netdev;
+
+ s->nic = qemu_new_nic(&net_imx_fec_info, &s->conf,
+ object_get_typename(OBJECT(dev)), DEVICE(dev)->id,
+ s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
+}
+
+static Property imx_fec_properties[] = {
+ DEFINE_NIC_PROPERTIES(IMXFECState, conf),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void imx_fec_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->vmsd = &vmstate_imx_fec;
+ dc->reset = imx_fec_reset;
+ dc->props = imx_fec_properties;
+ dc->realize = imx_fec_realize;
+}
+
+static const TypeInfo imx_fec_info = {
+ .name = TYPE_IMX_FEC,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMXFECState),
+ .class_init = imx_fec_class_init,
+};
+
+static void imx_fec_register_types(void)
+{
+ type_register_static(&imx_fec_info);
+}
+
+DeviceState *imx_fec_create(int nic, const hwaddr base, qemu_irq irq)
+{
+ NICInfo *nd;
+ DeviceState *dev;
+ SysBusDevice *sbd;
+
+ if (nic >= MAX_NICS) {
+ hw_error("Cannot assign nic %d: QEMU supports only %d ports\n",
+ nic, MAX_NICS);
+ }
+
+ nd = &nd_table[nic];
+
+ qemu_check_nic_model(nd, TYPE_IMX_FEC);
+ dev = qdev_create(NULL, TYPE_IMX_FEC);
+ qdev_set_nic_properties(dev, nd);
+ qdev_init_nofail(dev);
+ sbd = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(sbd, 0, base);
+ sysbus_connect_irq(sbd, 0, irq);
+
+ return dev;
+};
+
+type_init(imx_fec_register_types)
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
new file mode 100644
index 0000000..9d5a8d3
--- /dev/null
+++ b/include/hw/net/imx_fec.h
@@ -0,0 +1,115 @@
+/*
+ * i.MX Fast Ethernet Controller emulation.
+ *
+ * Copyright (c) 2013 Jean-Christophe Dubois. <jcd@tribudubois.net>
+ *
+ * Based on Coldfire Fast Ethernet Controller emulation.
+ *
+ * Copyright (c) 2007 CodeSourcery.
+ *
+ * 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/>.
+ */
+
+#ifndef IMX_FEC_H
+#define IMX_FEC_H
+
+#define TYPE_IMX_FEC "imx.fec"
+#define IMX_FEC(obj) OBJECT_CHECK(IMXFECState, (obj), TYPE_IMX_FEC)
+
+#include "hw/sysbus.h"
+#include "net/net.h"
+
+#define FEC_MAX_FRAME_SIZE 2032
+
+#define FEC_INT_HB (1 << 31)
+#define FEC_INT_BABR (1 << 30)
+#define FEC_INT_BABT (1 << 29)
+#define FEC_INT_GRA (1 << 28)
+#define FEC_INT_TXF (1 << 27)
+#define FEC_INT_TXB (1 << 26)
+#define FEC_INT_RXF (1 << 25)
+#define FEC_INT_RXB (1 << 24)
+#define FEC_INT_MII (1 << 23)
+#define FEC_INT_EBERR (1 << 22)
+#define FEC_INT_LC (1 << 21)
+#define FEC_INT_RL (1 << 20)
+#define FEC_INT_UN (1 << 19)
+
+#define FEC_EN 2
+#define FEC_RESET 1
+
+/* Buffer Descriptor. */
+typedef struct {
+ uint16_t length;
+ uint16_t flags;
+ uint32_t data;
+} IMXFECBufDesc;
+
+#define FEC_BD_R (1 << 15)
+#define FEC_BD_E (1 << 15)
+#define FEC_BD_O1 (1 << 14)
+#define FEC_BD_W (1 << 13)
+#define FEC_BD_O2 (1 << 12)
+#define FEC_BD_L (1 << 11)
+#define FEC_BD_TC (1 << 10)
+#define FEC_BD_ABC (1 << 9)
+#define FEC_BD_M (1 << 8)
+#define FEC_BD_BC (1 << 7)
+#define FEC_BD_MC (1 << 6)
+#define FEC_BD_LG (1 << 5)
+#define FEC_BD_NO (1 << 4)
+#define FEC_BD_CR (1 << 2)
+#define FEC_BD_OV (1 << 1)
+#define FEC_BD_TR (1 << 0)
+
+typedef struct {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ NICState *nic;
+ NICConf conf;
+ qemu_irq irq;
+ MemoryRegion iomem;
+
+ uint32_t irq_state;
+ uint32_t eir;
+ uint32_t eimr;
+ uint32_t rx_enabled;
+ uint32_t rx_descriptor;
+ uint32_t tx_descriptor;
+ uint32_t ecr;
+ uint32_t mmfr;
+ uint32_t mscr;
+ uint32_t mibc;
+ uint32_t rcr;
+ uint32_t tcr;
+ uint32_t tfwr;
+ uint32_t frsr;
+ uint32_t erdsr;
+ uint32_t etdsr;
+ uint32_t emrbr;
+ uint32_t miigsk_cfgr;
+ uint32_t miigsk_enr;
+
+ uint32_t phy_status;
+ uint32_t phy_control;
+ uint32_t phy_advertise;
+ uint32_t phy_int;
+ uint32_t phy_int_mask;
+} IMXFECState;
+
+DeviceState *imx_fec_create(int nic, const hwaddr base, qemu_irq irq);
+
+#endif
--
2.1.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v8 08/11] i.MX: Add I2C controller emulator
2015-06-29 20:11 [Qemu-devel] [PATCH v8 00/11] i.MX: Add i.MX25 support through the 3DS evaluation board Jean-Christophe Dubois
` (6 preceding siblings ...)
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 07/11] i.MX: Add FEC Ethernet Emulator Jean-Christophe Dubois
@ 2015-06-29 20:12 ` Jean-Christophe Dubois
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 09/11] i.MX25: Add the i.MX25 SOC support Jean-Christophe Dubois
` (2 subsequent siblings)
10 siblings, 0 replies; 17+ messages in thread
From: Jean-Christophe Dubois @ 2015-06-29 20:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Jean-Christophe Dubois
The slave mode is not implemented.
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
Reviewed-by: Peter Crosthwaite <crosthwaite.peter@gmail.com>
---
Changes since v1:
* none
Changes since v2:
* use QOM cast
* reworked debug printf
* use CamelCase for state type
* warn with qemu_log_mask(LOG_GUEST_ERROR) or qemu_log_mask(LOG_UNIMP)
* move to dma_memory_read/write API
* rework interrupt handling
* use qemu_flush_queued_packets() in rx_enable()
Changes since v3:
* use realise for device initialization
* More QOM cast
* reworked debug printf some more
* standardise GPL header
* use CamelCase for buffer descriptor type
Changes since v4:
* none
Changes since v5:
* replace hw_error() with qemu_log_mask(LOG_GUEST_ERROR, ...)
* remove reformating of imx.h header file.
* remove unnecessary spaces.
Changes since v6:
* port to new memory API
Changes since v7:
* refactor to be used by SOC
default-configs/arm-softmmu.mak | 2 +
hw/i2c/Makefile.objs | 1 +
hw/i2c/imx_i2c.c | 339 ++++++++++++++++++++++++++++++++++++++++
include/hw/i2c/imx_i2c.h | 85 ++++++++++
4 files changed, 427 insertions(+)
create mode 100644 hw/i2c/imx_i2c.c
create mode 100644 include/hw/i2c/imx_i2c.h
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index d21ff7b..c6f509d 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -99,6 +99,8 @@ CONFIG_ALLWINNER_A10_PIT=y
CONFIG_ALLWINNER_A10_PIC=y
CONFIG_ALLWINNER_A10=y
+CONFIG_IMX_I2C=y
+
CONFIG_XIO3130=y
CONFIG_IOH3420=y
CONFIG_I82801B11=y
diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
index 0f13060..aeb8f38 100644
--- a/hw/i2c/Makefile.objs
+++ b/hw/i2c/Makefile.objs
@@ -4,4 +4,5 @@ common-obj-$(CONFIG_ACPI_X86) += smbus_ich9.o
common-obj-$(CONFIG_APM) += pm_smbus.o
common-obj-$(CONFIG_BITBANG_I2C) += bitbang_i2c.o
common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o
+common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o
obj-$(CONFIG_OMAP) += omap_i2c.o
diff --git a/hw/i2c/imx_i2c.c b/hw/i2c/imx_i2c.c
new file mode 100644
index 0000000..468712b
--- /dev/null
+++ b/hw/i2c/imx_i2c.c
@@ -0,0 +1,339 @@
+/*
+ * i.MX I2C Bus Serial Interface Emulation
+ *
+ * Copyright (C) 2013 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.
+ *
+ * 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/>.
+ *
+ */
+
+#include "hw/i2c/imx_i2c.h"
+#include "hw/i2c/i2c.h"
+
+#ifndef IMX_I2C_DEBUG
+#define IMX_I2C_DEBUG 0
+#endif
+
+#if IMX_I2C_DEBUG
+#define DPRINT(fmt, args...) \
+ do { fprintf(stderr, "%s: "fmt, __func__, ## args); } while (0)
+
+static const char *imx_i2c_get_regname(unsigned offset)
+{
+ switch (offset) {
+ case IADR_ADDR:
+ return "IADR";
+ case IFDR_ADDR:
+ return "IFDR";
+ case I2CR_ADDR:
+ return "I2CR";
+ case I2SR_ADDR:
+ return "I2SR";
+ case I2DR_ADDR:
+ return "I2DR";
+ default:
+ return "[?]";
+ }
+}
+#else
+#define DPRINT(fmt, args...) do { } while (0)
+#endif
+
+static inline bool imx_i2c_is_enabled(IMXI2CState *s)
+{
+ return s->i2cr & I2CR_IEN;
+}
+
+static inline bool imx_i2c_interrupt_is_enabled(IMXI2CState *s)
+{
+ return s->i2cr & I2CR_IIEN;
+}
+
+static inline bool imx_i2c_is_master(IMXI2CState *s)
+{
+ return s->i2cr & I2CR_MSTA;
+}
+
+static inline bool imx_i2c_direction_is_tx(IMXI2CState *s)
+{
+ return s->i2cr & I2CR_MTX;
+}
+
+static void imx_i2c_reset(DeviceState *dev)
+{
+ IMXI2CState *s = IMX_I2C(dev);
+
+ if (s->address != ADDR_RESET) {
+ i2c_end_transfer(s->bus);
+ }
+
+ s->address = ADDR_RESET;
+ s->iadr = IADR_RESET;
+ s->ifdr = IFDR_RESET;
+ s->i2cr = I2CR_RESET;
+ s->i2sr = I2SR_RESET;
+ s->i2dr_read = I2DR_RESET;
+ s->i2dr_write = I2DR_RESET;
+}
+
+static inline void imx_i2c_raise_interrupt(IMXI2CState *s)
+{
+ /*
+ * raise an interrupt if the device is enabled and it is configured
+ * to generate some interrupts.
+ */
+ if (imx_i2c_is_enabled(s) && imx_i2c_interrupt_is_enabled(s)) {
+ s->i2sr |= I2SR_IIF;
+ qemu_irq_raise(s->irq);
+ }
+}
+
+static uint64_t imx_i2c_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+ uint16_t value;
+ IMXI2CState *s = IMX_I2C(opaque);
+
+ switch (offset) {
+ case IADR_ADDR:
+ value = s->iadr;
+ break;
+ case IFDR_ADDR:
+ value = s->ifdr;
+ break;
+ case I2CR_ADDR:
+ value = s->i2cr;
+ break;
+ case I2SR_ADDR:
+ value = s->i2sr;
+ break;
+ case I2DR_ADDR:
+ value = s->i2dr_read;
+
+ if (imx_i2c_is_master(s)) { /* master mode */
+ int ret = 0xff;
+
+ if (s->address == ADDR_RESET) {
+ /* something is wrong as the address is not set */
+ qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Trying to read "
+ "without specifying the slave address\n",
+ TYPE_IMX_I2C, __func__);
+ } else if (s->i2cr & I2CR_MTX) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Trying to read "
+ "but MTX is set\n", TYPE_IMX_I2C, __func__);
+ } else {
+ /* get the next byte */
+ ret = i2c_recv(s->bus);
+
+ if (ret >= 0) {
+ imx_i2c_raise_interrupt(s);
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: read failed "
+ "for device 0x%02x\n", TYPE_IMX_I2C,
+ __func__, s->address);
+ ret = 0xff;
+ }
+ }
+
+ s->i2dr_read = ret;
+ } else {
+ qemu_log_mask(LOG_UNIMP, "%s[%s]: slave mode not implemented\n",
+ TYPE_IMX_I2C, __func__);
+ }
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
+ TYPE_IMX_I2C, __func__, s->address);
+ value = 0;
+ break;
+ }
+
+ DPRINT("read %s [0x%02x] -> 0x%02x\n", imx_i2c_get_regname(offset),
+ (unsigned int)offset, value);
+
+ return (uint64_t)value;
+}
+
+static void imx_i2c_write(void *opaque, hwaddr offset,
+ uint64_t value, unsigned size)
+{
+ IMXI2CState *s = IMX_I2C(opaque);
+
+ DPRINT("write %s [0x%02x] <- 0x%02x\n", imx_i2c_get_regname(offset),
+ (unsigned int)offset, (int)value);
+
+ value &= 0xff;
+
+ switch (offset) {
+ case IADR_ADDR:
+ s->iadr = value & IADR_MASK;
+ /* i2c_set_slave_address(s->bus, (uint8_t)s->iadr); */
+ break;
+ case IFDR_ADDR:
+ s->ifdr = value & IFDR_MASK;
+ break;
+ case I2CR_ADDR:
+ if (imx_i2c_is_enabled(s) && ((value & I2CR_IEN) == 0)) {
+ /* This is a soft reset. IADR is preserved during soft resets */
+ uint16_t iadr = s->iadr;
+ imx_i2c_reset(DEVICE(s));
+ s->iadr = iadr;
+ } else { /* normal write */
+ s->i2cr = value & I2CR_MASK;
+
+ if (imx_i2c_is_master(s)) { /* master mode */
+ /* set the bus to busy */
+ s->i2sr |= I2SR_IBB;
+ } else { /* slave mode */
+ /* bus is not busy anymore */
+ s->i2sr &= ~I2SR_IBB;
+
+ /*
+ * if we unset the master mode then it ends the ongoing
+ * transfer if any
+ */
+ if (s->address != ADDR_RESET) {
+ i2c_end_transfer(s->bus);
+ s->address = ADDR_RESET;
+ }
+ }
+
+ if (s->i2cr & I2CR_RSTA) { /* Restart */
+ /* if this is a restart then it ends the ongoing transfer */
+ if (s->address != ADDR_RESET) {
+ i2c_end_transfer(s->bus);
+ s->address = ADDR_RESET;
+ s->i2cr &= ~I2CR_RSTA;
+ }
+ }
+ }
+ break;
+ case I2SR_ADDR:
+ /*
+ * if the user writes 0 to IIF then lower the interrupt and
+ * reset the bit
+ */
+ if ((s->i2sr & I2SR_IIF) && !(value & I2SR_IIF)) {
+ s->i2sr &= ~I2SR_IIF;
+ qemu_irq_lower(s->irq);
+ }
+
+ /*
+ * if the user writes 0 to IAL, reset the bit
+ */
+ if ((s->i2sr & I2SR_IAL) && !(value & I2SR_IAL)) {
+ s->i2sr &= ~I2SR_IAL;
+ }
+
+ break;
+ case I2DR_ADDR:
+ /* if the device is not enabled, nothing to do */
+ if (!imx_i2c_is_enabled(s)) {
+ break;
+ }
+
+ s->i2dr_write = value & I2DR_MASK;
+
+ if (imx_i2c_is_master(s)) { /* master mode */
+ /* If this is the first write cycle then it is the slave addr */
+ if (s->address == ADDR_RESET) {
+ if (i2c_start_transfer(s->bus, extract32(s->i2dr_write, 1, 7),
+ extract32(s->i2dr_write, 0, 1))) {
+ /* if non zero is returned, the adress is not valid */
+ s->i2sr |= I2SR_RXAK;
+ } else {
+ s->address = s->i2dr_write;
+ s->i2sr &= ~I2SR_RXAK;
+ imx_i2c_raise_interrupt(s);
+ }
+ } else { /* This is a normal data write */
+ if (i2c_send(s->bus, s->i2dr_write)) {
+ /* if the target return non zero then end the transfer */
+ s->i2sr |= I2SR_RXAK;
+ s->address = ADDR_RESET;
+ i2c_end_transfer(s->bus);
+ } else {
+ s->i2sr &= ~I2SR_RXAK;
+ imx_i2c_raise_interrupt(s);
+ }
+ }
+ } else {
+ qemu_log_mask(LOG_UNIMP, "%s[%s]: slave mode not implemented\n",
+ TYPE_IMX_I2C, __func__);
+ }
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s[%s]: Bad address at offset %d\n",
+ TYPE_IMX_I2C, __func__, s->address);
+ break;
+ }
+}
+
+static const MemoryRegionOps imx_i2c_ops = {
+ .read = imx_i2c_read,
+ .write = imx_i2c_write,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 2,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription imx_i2c_vmstate = {
+ .name = TYPE_IMX_I2C,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT16(address, IMXI2CState),
+ VMSTATE_UINT16(iadr, IMXI2CState),
+ VMSTATE_UINT16(ifdr, IMXI2CState),
+ VMSTATE_UINT16(i2cr, IMXI2CState),
+ VMSTATE_UINT16(i2sr, IMXI2CState),
+ VMSTATE_UINT16(i2dr_read, IMXI2CState),
+ VMSTATE_UINT16(i2dr_write, IMXI2CState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void imx_i2c_realize(DeviceState *dev, Error **errp)
+{
+ IMXI2CState *s = IMX_I2C(dev);
+
+ memory_region_init_io(&s->iomem, OBJECT(s), &imx_i2c_ops, s, TYPE_IMX_I2C,
+ IMX_I2C_MEM_SIZE);
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
+ s->bus = i2c_init_bus(DEVICE(dev), "i2c");
+}
+
+static void imx_i2c_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->vmsd = &imx_i2c_vmstate;
+ dc->reset = imx_i2c_reset;
+ dc->realize = imx_i2c_realize;
+}
+
+static const TypeInfo imx_i2c_type_info = {
+ .name = TYPE_IMX_I2C,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMXI2CState),
+ .class_init = imx_i2c_class_init,
+};
+
+static void imx_i2c_register_types(void)
+{
+ type_register_static(&imx_i2c_type_info);
+}
+
+type_init(imx_i2c_register_types)
diff --git a/include/hw/i2c/imx_i2c.h b/include/hw/i2c/imx_i2c.h
new file mode 100644
index 0000000..1c511ec
--- /dev/null
+++ b/include/hw/i2c/imx_i2c.h
@@ -0,0 +1,85 @@
+/*
+ * i.MX I2C Bus Serial Interface registers definition
+ *
+ * Copyright (C) 2013 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.
+ *
+ * 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/>.
+ *
+ */
+
+#ifndef __IMX_I2C_H_
+#define __IMX_I2C_H_
+
+#include <hw/sysbus.h>
+
+#define TYPE_IMX_I2C "imx.i2c"
+#define IMX_I2C(obj) OBJECT_CHECK(IMXI2CState, (obj), TYPE_IMX_I2C)
+
+#define IMX_I2C_MEM_SIZE 0x14
+
+/* i.MX I2C memory map */
+#define IADR_ADDR 0x00 /* address register */
+#define IFDR_ADDR 0x04 /* frequency divider register */
+#define I2CR_ADDR 0x08 /* control register */
+#define I2SR_ADDR 0x0c /* status register */
+#define I2DR_ADDR 0x10 /* data register */
+
+#define IADR_MASK 0xFE
+#define IADR_RESET 0
+
+#define IFDR_MASK 0x3F
+#define IFDR_RESET 0
+
+#define I2CR_IEN (1 << 7)
+#define I2CR_IIEN (1 << 6)
+#define I2CR_MSTA (1 << 5)
+#define I2CR_MTX (1 << 4)
+#define I2CR_TXAK (1 << 3)
+#define I2CR_RSTA (1 << 2)
+#define I2CR_MASK 0xFC
+#define I2CR_RESET 0
+
+#define I2SR_ICF (1 << 7)
+#define I2SR_IAAF (1 << 6)
+#define I2SR_IBB (1 << 5)
+#define I2SR_IAL (1 << 4)
+#define I2SR_SRW (1 << 2)
+#define I2SR_IIF (1 << 1)
+#define I2SR_RXAK (1 << 0)
+#define I2SR_MASK 0xE9
+#define I2SR_RESET 0x81
+
+#define I2DR_MASK 0xFF
+#define I2DR_RESET 0
+
+#define ADDR_RESET 0xFF00
+
+typedef struct IMXI2CState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion iomem;
+ I2CBus *bus;
+ qemu_irq irq;
+
+ uint16_t address;
+
+ uint16_t iadr;
+ uint16_t ifdr;
+ uint16_t i2cr;
+ uint16_t i2sr;
+ uint16_t i2dr_read;
+ uint16_t i2dr_write;
+} IMXI2CState;
+
+#endif /* __IMX_I2C_H_ */
--
2.1.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v8 09/11] i.MX25: Add the i.MX25 SOC support
2015-06-29 20:11 [Qemu-devel] [PATCH v8 00/11] i.MX: Add i.MX25 support through the 3DS evaluation board Jean-Christophe Dubois
` (7 preceding siblings ...)
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 08/11] i.MX: Add I2C controller emulator Jean-Christophe Dubois
@ 2015-06-29 20:12 ` Jean-Christophe Dubois
2015-06-30 7:29 ` Peter Crosthwaite
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 10/11] i.MX25: Add support for the i.MX25 PDK 3DS Jean-Christophe Dubois
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 11/11] i.MX: Add qtest support for I2C device emulator Jean-Christophe Dubois
10 siblings, 1 reply; 17+ messages in thread
From: Jean-Christophe Dubois @ 2015-06-29 20:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Jean-Christophe Dubois
For now we do support the foolowing devices:
* GPT timers (from i.MX31)
* EPIT timers (from i.MX31)
* CCM (from i.MX31)
* AVIC (from i.MX31)
* UART (from i.MX31)
* Ethernet FEC port
* I2C controller
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
---
Changes since v1:
* not present on v1
Changes since v2:
* not present on v2
Changes since v3:
* not present on v3
Changes since v4:
* not present on v4
Changes since v5:
* not present on v5
Changes since v6:
* not present on v6
Changes since v7:
* Added a SOC specific file for i.MX25
default-configs/arm-softmmu.mak | 1 +
hw/arm/Makefile.objs | 1 +
hw/arm/fsl-imx25.c | 304 ++++++++++++++++++++++++++++++++++++++++
include/hw/arm/fsl-imx25.h | 52 +++++++
4 files changed, 358 insertions(+)
create mode 100644 hw/arm/fsl-imx25.c
create mode 100644 include/hw/arm/fsl-imx25.h
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index c6f509d..057f39c 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -99,6 +99,7 @@ CONFIG_ALLWINNER_A10_PIT=y
CONFIG_ALLWINNER_A10_PIC=y
CONFIG_ALLWINNER_A10=y
+CONFIG_FSL_IMX25=y
CONFIG_IMX_I2C=y
CONFIG_XIO3130=y
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index cf346c1..b89c31d 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -13,3 +13,4 @@ obj-y += omap1.o omap2.o strongarm.o
obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
+obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o
diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
new file mode 100644
index 0000000..b2db548
--- /dev/null
+++ b/hw/arm/fsl-imx25.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2013 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * i.MX25 SOC emulation.
+ *
+ * Based on hw/arm/xlnx-zynqmp.c
+ *
+ * Copyright (C) 2015 Xilinx Inc
+ * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com>
+ *
+ * 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/>.
+ */
+
+#include "hw/arm/fsl-imx25.h"
+#include "sysemu/sysemu.h"
+
+/* Memory map for 3D-Stack Emulation Baseboard:
+ * 0x00000000-0x00003fff 16k ROM IGNORED
+ * 0x00004000-0x00403fff Reserved IGNORED
+ * 0x00404000-0x00408fff 20k ROM IGNORED
+ * 0x00409000-0x0fffffff Reserved IGNORED
+ * 0x10000000-0x1fffffff Reserved IGNORED
+ * 0x20000000-0x2fffffff Reserved IGNORED
+ * 0x30000000-0x3fffffff Reserved IGNORED
+ * 0x40000000-0x43efffff Reserved IGNORED
+ * 0x43f00000-0x6fffffff I.MX25 Internal Register Space
+ * 0x43f00000 IO_AREA0
+ * 0x43f80000 I2C0 EMULATED
+ * 0x43f84000 I2C2 EMULATED
+ * 0x43f98000 I2C1 EMULATED
+ * 0x43f90000 UART1 EMULATED
+ * 0x43f94000 UART2 EMULATED
+ * 0x43fb0000 UART4 IGNORED
+ * 0x43fb4000 UART5 IGNORED
+ * 0x5000c000 UART3 EMULATED
+ * 0x50038000 FEC EMULATED
+ * 0x53f80000 CCM EMULATED
+ * 0x53f84000 GPT 4 EMULATED
+ * 0x53f88000 GPT 3 EMULATED
+ * 0x53f8c000 GPT 2 EMULATED
+ * 0x53f90000 GPT 1 EMULATED
+ * 0x53f94000 PIT 1 EMULATED
+ * 0x53f98000 PIT 2 EMULATED
+ * 0x53f9c000 GPIO-4 EMULATED
+ * 0x53fa4000 GPIO-3 EMULATED
+ * 0x53fcc000 GPIO-1 EMULATED
+ * 0x53fd0000 GPIO-2 EMULATED
+ * 0x68000000 ASIC EMULATED
+ * 0x78000000-0x7801ffff SRAM EMULATED
+ * 0x78020000-0x7fffffff SRAM Aliasing EMULATED
+ * 0x80000000-0x87ffffff RAM + Alias EMULATED
+ * 0x90000000-0x9fffffff RAM + Alias EMULATED
+ * 0xa0000000-0xa7ffffff Flash IGNORED
+ * 0xa8000000-0xafffffff Flash IGNORED
+ * 0xb0000000-0xb1ffffff SRAM IGNORED
+ * 0xb2000000-0xb3ffffff SRAM IGNORED
+ * 0xb4000000-0xb5ffffff CS4 IGNORED
+ * 0xb6000000-0xb8000fff Reserved IGNORED
+ * 0xb8001000-0xb8001fff SDRAM CTRL reg IGNORED
+ * 0xb8002000-0xb8002fff WEIM CTRL reg IGNORED
+ * 0xb8003000-0xb8003fff M3IF CTRL reg IGNORED
+ * 0xb8004000-0xb8004fff EMI CTRL reg IGNORED
+ * 0xb8005000-0xbaffffff Reserved IGNORED
+ * 0xbb000000-0xbb000fff NAND flash area buf IGNORED
+ * 0xbb001000-0xbb0011ff NAND flash reserved IGNORED
+ * 0xbb001200-0xbb001dff Reserved IGNORED
+ * 0xbb001e00-0xbb001fff NAN flash CTRL reg IGNORED
+ * 0xbb012000-0xbfffffff Reserved IGNORED
+ * 0xc0000000-0xffffffff Reserved IGNORED
+ */
+
+static void fsl_imx25_init(Object *obj)
+{
+ FslImx25State *s = FSL_IMX25(obj);
+ int i;
+
+ object_initialize(&s->cpu, sizeof(s->cpu), "arm926-" TYPE_ARM_CPU);
+
+ object_initialize(&s->avic, sizeof(s->avic), TYPE_IMX_AVIC);
+ qdev_set_parent_bus(DEVICE(&s->avic), sysbus_get_default());
+
+ object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX_CCM);
+ qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default());
+
+ for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
+ if (i >= MAX_SERIAL_PORTS) {
+ break;
+ }
+ object_initialize(&s->uart[i], sizeof(s->uart[i]), TYPE_IMX_SERIAL);
+ qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus_get_default());
+ }
+
+ for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
+ object_initialize(&s->gpt[i], sizeof(s->gpt[i]), TYPE_IMX_GPT);
+ qdev_set_parent_bus(DEVICE(&s->gpt[i]), sysbus_get_default());
+ }
+
+ for (i = 0; i < FSL_IMX25_NUM_EPITS; i++) {
+ object_initialize(&s->epit[i], sizeof(s->epit[i]), TYPE_IMX_EPIT);
+ qdev_set_parent_bus(DEVICE(&s->epit[i]), sysbus_get_default());
+ }
+
+ object_initialize(&s->fec, sizeof(s->fec), TYPE_IMX_FEC);
+ qdev_set_parent_bus(DEVICE(&s->fec), sysbus_get_default());
+
+ for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) {
+ object_initialize(&s->i2c[i], sizeof(s->i2c[i]), TYPE_IMX_I2C);
+ qdev_set_parent_bus(DEVICE(&s->i2c[i]), sysbus_get_default());
+ }
+}
+
+static void fsl_imx25_realize(DeviceState *dev, Error **errp)
+{
+ FslImx25State *s = FSL_IMX25(dev);
+ //MemoryRegion *system_memory = get_system_memory();
+ uint8_t i;
+ Error *err = NULL;
+
+ /* Initialize the CPU */
+ object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
+ if (err) {
+ error_propagate((errp), (err));
+ return;
+ }
+
+ /* Initialize the PIC */
+ object_property_set_bool(OBJECT(&s->avic), true, "realized", &err);
+ if (err) {
+ error_propagate((errp), (err));
+ return;
+ }
+ /* Connect the PIC interrupt to the CPU */
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->avic), 0, 0x68000000);
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 0,
+ qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ));
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 1,
+ qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ));
+
+ /* Initialize the CCM */
+ object_property_set_bool(OBJECT(&s->ccm), true, "realized", &err);
+ if (err) {
+ error_propagate((errp), (err));
+ return;
+ }
+ /* Map CCM memory */
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, 0x53f80000);
+
+ /* Initialize all UARTS */
+ for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
+ static const struct {
+ hwaddr addr;
+ unsigned int irq;
+ } serial_table[FSL_IMX25_NUM_UARTS] = {
+ { 0x43f90000, 45 },
+ { 0x43f94000, 32 },
+ { 0x5000c000, 18 },
+ { 0x50008000, 5 },
+ { 0x5002c000, 40 }
+ };
+
+ /* Bail out if we exeeded Qemu UART count */
+ if (i >= MAX_SERIAL_PORTS) {
+ break;
+ }
+ /* Initialize the UART */
+ object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err);
+ if (err) {
+ error_propagate((errp), (err));
+ return;
+ }
+ /* Map UART memory */
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->uart[i]), 0, serial_table[i].addr);
+ /* Connet UART IRQ to PIC */
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->uart[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->avic),
+ serial_table[i].irq));
+ }
+
+ /* Initialize all GPT timers */
+ for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
+ static const struct {
+ hwaddr addr;
+ unsigned int irq;
+ } gpt_table[FSL_IMX25_NUM_GPTS] = {
+ { 0x53f84000, 1 },
+ { 0x53f88000, 29 },
+ { 0x53f8c000, 53 },
+ { 0x53f90000, 54 }
+ };
+
+ s->gpt[i].ccm = DEVICE(&s->ccm);
+
+ /* Initialize the GPT */
+ object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized", &err);
+ if (err) {
+ error_propagate((errp), (err));
+ return;
+ }
+ /* Map GPT memory */
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpt[i]), 0, gpt_table[i].addr);
+ /* Connet GPT IRQ to PIC */
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->gpt[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->avic),
+ gpt_table[i].irq));
+ }
+
+ /* Initialize all EPIT timers */
+ for (i = 0; i < FSL_IMX25_NUM_EPITS; i++) {
+ static const struct {
+ hwaddr addr;
+ unsigned int irq;
+ } epit_table[FSL_IMX25_NUM_EPITS] = {
+ { 0x53f94000, 28 },
+ { 0x53f98000, 27 }
+ };
+
+ s->epit[i].ccm = DEVICE(&s->ccm);
+
+ /* Initialize the EPIT */
+ object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err);
+ if (err) {
+ error_propagate((errp), (err));
+ return;
+ }
+ /* Map EPIT memory */
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->epit[i]), 0, epit_table[i].addr);
+ /* Connet EPIT IRQ to PIC */
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->epit[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->avic),
+ epit_table[i].irq));
+ }
+
+ /* Initialize the FEC */
+ qdev_set_nic_properties(DEVICE(&s->fec), &nd_table[0]);
+ object_property_set_bool(OBJECT(&s->fec), true, "realized", &err);
+ if (err) {
+ error_propagate((errp), (err));
+ return;
+ }
+ /* Map FEC memory */
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->fec), 0, 0x50038000);
+ /* Connet FEC IRQ to PIC */
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->fec), 0,
+ qdev_get_gpio_in(DEVICE(&s->avic), 57));
+
+
+ /* Initialize all I2C */
+ for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) {
+ static const struct {
+ hwaddr addr;
+ unsigned int irq;
+ } i2c_table[FSL_IMX25_NUM_I2CS] = {
+ { 0x43f80000, 3 },
+ { 0x43f98000, 4 },
+ { 0x43f84000, 10 }
+ };
+
+ /* Initialize the I2C */
+ object_property_set_bool(OBJECT(&s->i2c[i]), true, "realized", &err);
+ if (err) {
+ error_propagate((errp), (err));
+ return;
+ }
+ /* Map I2C memory */
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c[i]), 0, i2c_table[i].addr);
+ /* Connet I2C IRQ to PIC */
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c[i]), 0,
+ qdev_get_gpio_in(DEVICE(&s->avic),
+ i2c_table[i].irq));
+ }
+}
+
+static void fsl_imx25_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->realize = fsl_imx25_realize;
+}
+
+static const TypeInfo fsl_imx25_type_info = {
+ .name = TYPE_FSL_IMX25,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(FslImx25State),
+ .instance_init = fsl_imx25_init,
+ .class_init = fsl_imx25_class_init,
+};
+
+static void fsl_imx25_register_types(void)
+{
+ type_register_static(&fsl_imx25_type_info);
+}
+
+type_init(fsl_imx25_register_types)
diff --git a/include/hw/arm/fsl-imx25.h b/include/hw/arm/fsl-imx25.h
new file mode 100644
index 0000000..43d89a1
--- /dev/null
+++ b/include/hw/arm/fsl-imx25.h
@@ -0,0 +1,52 @@
+/*
+ * Freescale i.MX25 SoC emulation
+ *
+ * Copyright (C) 2015 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.
+ *
+ * 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.
+ */
+
+#ifndef FSL_IMX25_H
+#define FSL_IMX25_H
+
+#include "hw/arm/arm.h"
+#include "hw/intc/imx_avic.h"
+#include "hw/misc/imx_ccm.h"
+#include "hw/char/imx_serial.h"
+#include "hw/timer/imx_gpt.h"
+#include "hw/timer/imx_epit.h"
+#include "hw/net/imx_fec.h"
+#include "hw/i2c/imx_i2c.h"
+
+#define TYPE_FSL_IMX25 "fsl,imx25"
+#define FSL_IMX25(obj) OBJECT_CHECK(FslImx25State, (obj), TYPE_FSL_IMX25)
+
+#define FSL_IMX25_NUM_UARTS 5
+#define FSL_IMX25_NUM_GPTS 4
+#define FSL_IMX25_NUM_EPITS 2
+#define FSL_IMX25_NUM_I2CS 3
+
+typedef struct {
+ /*< private >*/
+ DeviceState parent_obj;
+
+ /*< public >*/
+ ARMCPU cpu;
+ IMXAVICState avic;
+ IMXCCMState ccm;
+ IMXSerialState uart[FSL_IMX25_NUM_UARTS];
+ IMXGPTState gpt[FSL_IMX25_NUM_GPTS];
+ IMXEPITState epit[FSL_IMX25_NUM_EPITS];
+ IMXFECState fec;
+ IMXI2CState i2c[FSL_IMX25_NUM_I2CS];
+} FslImx25State;
+
+#endif // FSL_IMX25_H
--
2.1.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v8 10/11] i.MX25: Add support for the i.MX25 PDK 3DS
2015-06-29 20:11 [Qemu-devel] [PATCH v8 00/11] i.MX: Add i.MX25 support through the 3DS evaluation board Jean-Christophe Dubois
` (8 preceding siblings ...)
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 09/11] i.MX25: Add the i.MX25 SOC support Jean-Christophe Dubois
@ 2015-06-29 20:12 ` Jean-Christophe Dubois
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 11/11] i.MX: Add qtest support for I2C device emulator Jean-Christophe Dubois
10 siblings, 0 replies; 17+ messages in thread
From: Jean-Christophe Dubois @ 2015-06-29 20:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Jean-Christophe Dubois
This just adds the required memory arround the i.MX25 SOC.
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
---
Changes since v1:
* Added a ds1338 I2C device for qtest purpose.
Changes since v2:
* none
Changes since v3:
* Rework GPL header
* use I2C constructor helper.
Changes since v4:
* use sysbus_create_simple() instead of I2C constructor helper
Changes since v5:
* Add ds1338 only for qtest mode.
* small comment fixes.
Changes since v6:
* Allow for more than 4 serial if suppoted by Qemu.
Changes since v7:
* Move the SOC part into its own file.
hw/arm/Makefile.objs | 2 +-
hw/arm/imx25_3ds.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 218 insertions(+), 1 deletion(-)
create mode 100644 hw/arm/imx25_3ds.c
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index b89c31d..c03228d 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -13,4 +13,4 @@ obj-y += omap1.o omap2.o strongarm.o
obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
-obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o
+obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_3ds.o
diff --git a/hw/arm/imx25_3ds.c b/hw/arm/imx25_3ds.c
new file mode 100644
index 0000000..ce97946
--- /dev/null
+++ b/hw/arm/imx25_3ds.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2013 Jean-Christophe Dubois <jcd@tribudubois.net>
+ *
+ * 3Dstack Board System emulation.
+ *
+ * Based on hw/arm/kzm.c
+ *
+ * Copyright (c) 2008 OKL and 2011 NICTA
+ * Written by Hans at OK-Labs
+ * Updated by Peter Chubb.
+ *
+ * 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/>.
+ */
+
+#include "hw/arm/fsl-imx25.h"
+#include "hw/boards.h"
+#include "qemu/error-report.h"
+#include "exec/address-spaces.h"
+#include "sysemu/qtest.h"
+#include "hw/i2c/i2c.h"
+
+/* Memory map for 3D-Stack Emulation Baseboard:
+ * 0x00000000-0x00003fff 16k ROM IGNORED
+ * 0x00004000-0x00403fff Reserved IGNORED
+ * 0x00404000-0x00408fff 20k ROM IGNORED
+ * 0x00409000-0x0fffffff Reserved IGNORED
+ * 0x10000000-0x1fffffff Reserved IGNORED
+ * 0x20000000-0x2fffffff Reserved IGNORED
+ * 0x30000000-0x3fffffff Reserved IGNORED
+ * 0x40000000-0x43efffff Reserved IGNORED
+ * 0x43f00000-0x6fffffff I.MX25 Internal Register Space
+ * 0x43f00000 IO_AREA0
+ * 0x43f80000 I2C0 EMULATED
+ * 0x43f84000 I2C2 EMULATED
+ * 0x43f98000 I2C1 EMULATED
+ * 0x43f90000 UART1 EMULATED
+ * 0x43f94000 UART2 EMULATED
+ * 0x43fb0000 UART4 IGNORED
+ * 0x43fb4000 UART5 IGNORED
+ * 0x5000c000 UART3 EMULATED
+ * 0x50038000 FEC EMULATED
+ * 0x53f80000 CCM EMULATED
+ * 0x53f84000 GPT 4 EMULATED
+ * 0x53f88000 GPT 3 EMULATED
+ * 0x53f8c000 GPT 2 EMULATED
+ * 0x53f90000 GPT 1 EMULATED
+ * 0x53f94000 PIT 1 EMULATED
+ * 0x53f98000 PIT 2 EMULATED
+ * 0x53f9c000 GPIO-4 EMULATED
+ * 0x53fa4000 GPIO-3 EMULATED
+ * 0x53fcc000 GPIO-1 EMULATED
+ * 0x53fd0000 GPIO-2 EMULATED
+ * 0x68000000 ASIC EMULATED
+ * 0x78000000-0x7801ffff SRAM EMULATED
+ * 0x78020000-0x7fffffff SRAM Aliasing EMULATED
+ * 0x80000000-0x87ffffff RAM + Alias EMULATED
+ * 0x90000000-0x9fffffff RAM + Alias EMULATED
+ * 0xa0000000-0xa7ffffff Flash IGNORED
+ * 0xa8000000-0xafffffff Flash IGNORED
+ * 0xb0000000-0xb1ffffff SRAM IGNORED
+ * 0xb2000000-0xb3ffffff SRAM IGNORED
+ * 0xb4000000-0xb5ffffff CS4 IGNORED
+ * 0xb6000000-0xb8000fff Reserved IGNORED
+ * 0xb8001000-0xb8001fff SDRAM CTRL reg IGNORED
+ * 0xb8002000-0xb8002fff WEIM CTRL reg IGNORED
+ * 0xb8003000-0xb8003fff M3IF CTRL reg IGNORED
+ * 0xb8004000-0xb8004fff EMI CTRL reg IGNORED
+ * 0xb8005000-0xbaffffff Reserved IGNORED
+ * 0xbb000000-0xbb000fff NAND flash area buf IGNORED
+ * 0xbb001000-0xbb0011ff NAND flash reserved IGNORED
+ * 0xbb001200-0xbb001dff Reserved IGNORED
+ * 0xbb001e00-0xbb001fff NAN flash CTRL reg IGNORED
+ * 0xbb012000-0xbfffffff Reserved IGNORED
+ * 0xc0000000-0xffffffff Reserved IGNORED
+ */
+
+typedef struct imx25_3ds {
+ FslImx25State soc;
+ MemoryRegion ram[2];
+ MemoryRegion ram_alias;
+ MemoryRegion sram;
+ MemoryRegion sram_alias;
+} imx25_3ds;
+
+#define IMX25_SRAM_ADDRESS (0x78000000)
+#define IMX25_SRAMSIZE (128*1024)
+#define IMX25_CS_SRAMSIZE (128*1024*1024)
+#define IMX25_3DS_ADDRESS (0x80000000)
+#define IMX25_CS_RAMSIZE (256*1024*1024)
+
+static struct arm_boot_info imx25_3ds_binfo;
+
+static void imx25_3ds_init(MachineState *machine)
+{
+ imx25_3ds *s = g_new0(imx25_3ds, 1);
+ Error *err = NULL;
+ int i;
+
+ object_initialize(&s->soc, sizeof(s->soc), TYPE_FSL_IMX25);
+ object_property_add_child(OBJECT(machine), "soc", OBJECT(&s->soc),
+ &error_abort);
+
+ object_property_set_bool(OBJECT(&s->soc), true, "realized", &err);
+ if (err != NULL) {
+ error_report("%s", error_get_pretty(err));
+ exit(1);
+ }
+
+ /* We need to initialize our memory */
+
+ if (machine->ram_size > (2 * IMX25_CS_RAMSIZE)) {
+ error_report("WARNING: RAM size " RAM_ADDR_FMT " above max supported, "
+ "reduced to %x", machine->ram_size,
+ 2 * IMX25_CS_RAMSIZE);
+ machine->ram_size = 2 * IMX25_CS_RAMSIZE;
+ }
+
+ /* create our main memory */
+ for (i = 0; i <= (machine->ram_size / IMX25_CS_RAMSIZE); i++) {
+ ram_addr_t blk_size = machine->ram_size - (IMX25_CS_RAMSIZE * i);
+ char ram_name[20];
+
+ if (blk_size > IMX25_CS_RAMSIZE) {
+ blk_size = IMX25_CS_RAMSIZE;
+ }
+
+ if (blk_size == 0) {
+ break;
+ }
+
+ sprintf(ram_name, "imx25.ram%d", i);
+
+ memory_region_init_ram(&s->ram[i], NULL, ram_name, blk_size, &error_abort);
+ vmstate_register_ram_global(&s->ram[i]);
+ memory_region_add_subregion(get_system_memory(), IMX25_3DS_ADDRESS
+ + (IMX25_CS_RAMSIZE * i), &s->ram[i]);
+
+ /* Add ram alias */
+ if (blk_size < IMX25_CS_RAMSIZE) {
+ char alias_name[20];
+
+ sprintf(alias_name, "ram.alias%d", i);
+
+ memory_region_init_alias(&s->ram_alias, NULL, alias_name,
+ &s->ram[i], 0,
+ IMX25_CS_RAMSIZE - blk_size);
+ memory_region_add_subregion(get_system_memory(), IMX25_3DS_ADDRESS
+ + (IMX25_CS_RAMSIZE * i) + blk_size,
+ &s->ram_alias);
+ break;
+ }
+ }
+
+ /* create the sram area */
+ memory_region_init_ram(&s->sram, NULL, "imx25.sram", IMX25_SRAMSIZE,
+ &error_abort);
+ vmstate_register_ram_global(&s->sram);
+ memory_region_add_subregion(get_system_memory(), IMX25_SRAM_ADDRESS,
+ &s->sram);
+
+ /* add sram alias */
+ memory_region_init_alias(&s->sram_alias, NULL, "sram.alias", &s->sram, 0,
+ IMX25_CS_SRAMSIZE - IMX25_SRAMSIZE);
+ memory_region_add_subregion(get_system_memory(),
+ IMX25_SRAM_ADDRESS + IMX25_SRAMSIZE,
+ &s->sram_alias);
+
+ imx25_3ds_binfo.ram_size = machine->ram_size;
+ imx25_3ds_binfo.kernel_filename = machine->kernel_filename;
+ imx25_3ds_binfo.kernel_cmdline = machine->kernel_cmdline;
+ imx25_3ds_binfo.initrd_filename = machine->initrd_filename;
+ imx25_3ds_binfo.loader_start = IMX25_3DS_ADDRESS;
+ imx25_3ds_binfo.board_id = 1771,
+ imx25_3ds_binfo.nb_cpus = 1;
+
+ /*
+ * We test explicitly for qtest here as it is not done (yet?) in
+ * arm_load_kernel(). Without this the "make check" command would
+ * fail.
+ */
+ if (!qtest_enabled()) {
+ arm_load_kernel(&s->soc.cpu, &imx25_3ds_binfo);
+ } else {
+ /*
+ * This I2C device doesn't exist on the real board.
+ * We add it here (only on qtest usage) to be able to do a bit
+ * of simple qtest. See "make check" for details.
+ */
+ i2c_create_slave((I2CBus *)qdev_get_child_bus(DEVICE(&s->soc.i2c[0]),
+ "i2c"),
+ "ds1338", 0x68);
+ }
+}
+
+static QEMUMachine imx25_3ds_machine = {
+ .name = "imx25_3ds",
+ .desc = "ARM i.MX25 PDK board (ARM926)",
+ .init = imx25_3ds_init,
+};
+
+static void imx25_3ds_machine_init(void)
+{
+ qemu_register_machine(&imx25_3ds_machine);
+}
+
+machine_init(imx25_3ds_machine_init)
--
2.1.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [Qemu-devel] [PATCH v8 11/11] i.MX: Add qtest support for I2C device emulator.
2015-06-29 20:11 [Qemu-devel] [PATCH v8 00/11] i.MX: Add i.MX25 support through the 3DS evaluation board Jean-Christophe Dubois
` (9 preceding siblings ...)
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 10/11] i.MX25: Add support for the i.MX25 PDK 3DS Jean-Christophe Dubois
@ 2015-06-29 20:12 ` Jean-Christophe Dubois
10 siblings, 0 replies; 17+ messages in thread
From: Jean-Christophe Dubois @ 2015-06-29 20:12 UTC (permalink / raw)
To: qemu-devel; +Cc: Jean-Christophe Dubois
This is using a ds1338 RTC chip on the I2C bus. This RTC chip is
not present on the real board.
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
---
Changes since v1:
* not present on v1
Changes since v2:
* use a common header file for I2C regs definition
Changes since v3:
* rework GPL headers.
Changes since v4:
* none
Changes since v5:
* none
Changes since v6:
* none
Changes since v7:
* adapt to new i.MX I2C header file.
tests/Makefile | 3 +
tests/ds1338-test.c | 75 ++++++++++++++++++
tests/libqos/i2c-imx.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++++
tests/libqos/i2c.h | 3 +
4 files changed, 290 insertions(+)
create mode 100644 tests/ds1338-test.c
create mode 100644 tests/libqos/i2c-imx.c
diff --git a/tests/Makefile b/tests/Makefile
index c5e4744..93890a8 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -193,6 +193,7 @@ check-qtest-sparc64-y = tests/endianness-test$(EXESUF)
gcov-files-sparc-y += hw/timer/m48t59.c
gcov-files-sparc64-y += hw/timer/m48t59.c
check-qtest-arm-y = tests/tmp105-test$(EXESUF)
+check-qtest-arm-y = tests/ds1338-test$(EXESUF)
gcov-files-arm-y += hw/misc/tmp105.c
check-qtest-arm-y += tests/virtio-blk-test$(EXESUF)
gcov-files-arm-y += arm-softmmu/hw/block/virtio-blk.c
@@ -342,6 +343,7 @@ libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o
libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o
libqos-pc-obj-y += tests/libqos/ahci.o
libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o
+libqos-imx-obj-y = $(libqos-obj-y) tests/libqos/i2c-imx.o
libqos-usb-obj-y = $(libqos-pc-obj-y) tests/libqos/usb.o
libqos-virtio-obj-y = $(libqos-pc-obj-y) tests/libqos/virtio.o tests/libqos/virtio-pci.o tests/libqos/virtio-mmio.o tests/libqos/malloc-generic.o
@@ -356,6 +358,7 @@ tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
tests/boot-order-test$(EXESUF): tests/boot-order-test.o $(libqos-obj-y)
tests/bios-tables-test$(EXESUF): tests/bios-tables-test.o $(libqos-obj-y)
tests/tmp105-test$(EXESUF): tests/tmp105-test.o $(libqos-omap-obj-y)
+tests/ds1338-test$(EXESUF): tests/ds1338-test.o $(libqos-imx-obj-y)
tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
tests/q35-test$(EXESUF): tests/q35-test.o $(libqos-pc-obj-y)
tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
diff --git a/tests/ds1338-test.c b/tests/ds1338-test.c
new file mode 100644
index 0000000..fbc989b
--- /dev/null
+++ b/tests/ds1338-test.c
@@ -0,0 +1,75 @@
+/*
+ * QTest testcase for the DS1338 RTC
+ *
+ * Copyright (c) 2013 Jean-Christophe Dubois
+ *
+ * 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/>.
+ */
+
+#include "libqtest.h"
+#include "libqos/i2c.h"
+
+#include <glib.h>
+
+#define IMX25_I2C_0_BASE 0x43F80000
+
+#define DS1338_ADDR 0x68
+
+static I2CAdapter *i2c;
+static uint8_t addr;
+
+#define bcd2bin(x) (((x) & 0x0f) + ((x) >> 4) * 10)
+
+static void send_and_receive(void)
+{
+ uint8_t cmd[1];
+ uint8_t resp[7];
+ time_t now = time(NULL);
+ struct tm *tm_ptr = gmtime(&now);
+
+ /* reset the index in the RTC memory */
+ cmd[0] = 0;
+ i2c_send(i2c, addr, cmd, 1);
+
+ /* retrieve the date */
+ i2c_recv(i2c, addr, resp, 7);
+
+ /* check retreived time againt local time */
+ g_assert_cmpuint(bcd2bin(resp[4]), == , tm_ptr->tm_mday);
+ g_assert_cmpuint(bcd2bin(resp[5]), == , 1 + tm_ptr->tm_mon);
+ g_assert_cmpuint(2000 + bcd2bin(resp[6]), == , 1900 + tm_ptr->tm_year);
+}
+
+int main(int argc, char **argv)
+{
+ QTestState *s = NULL;
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+
+ s = qtest_start("-display none -machine imx25_3ds");
+ i2c = imx_i2c_create(IMX25_I2C_0_BASE);
+ addr = DS1338_ADDR;
+
+ qtest_add_func("/ds1338/tx-rx", send_and_receive);
+
+ ret = g_test_run();
+
+ if (s) {
+ qtest_quit(s);
+ }
+ g_free(i2c);
+
+ return ret;
+}
diff --git a/tests/libqos/i2c-imx.c b/tests/libqos/i2c-imx.c
new file mode 100644
index 0000000..b5cef66
--- /dev/null
+++ b/tests/libqos/i2c-imx.c
@@ -0,0 +1,209 @@
+/*
+ * QTest i.MX I2C driver
+ *
+ * Copyright (c) 2013 Jean-Christophe Dubois
+ *
+ * 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/>.
+ */
+
+#include "libqos/i2c.h"
+
+#include <glib.h>
+#include <string.h>
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+
+#include "hw/i2c/imx_i2c.h"
+
+enum IMXI2CDirection {
+ IMX_I2C_READ,
+ IMX_I2C_WRITE,
+};
+
+typedef struct IMXI2C {
+ I2CAdapter parent;
+
+ uint64_t addr;
+} IMXI2C;
+
+
+static void imx_i2c_set_slave_addr(IMXI2C *s, uint8_t addr,
+ enum IMXI2CDirection direction)
+{
+ writeb(s->addr + I2DR_ADDR, (addr << 1) |
+ (direction == IMX_I2C_READ ? 1 : 0));
+}
+
+static void imx_i2c_send(I2CAdapter *i2c, uint8_t addr,
+ const uint8_t *buf, uint16_t len)
+{
+ IMXI2C *s = (IMXI2C *)i2c;
+ uint8_t data;
+ uint8_t status;
+ uint16_t size = 0;
+
+ if (!len) {
+ return;
+ }
+
+ /* set the bus for write */
+ data = I2CR_IEN |
+ I2CR_IIEN |
+ I2CR_MSTA |
+ I2CR_MTX |
+ I2CR_TXAK;
+
+ writeb(s->addr + I2CR_ADDR, data);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IBB) != 0);
+
+ /* set the slave address */
+ imx_i2c_set_slave_addr(s, addr, IMX_I2C_WRITE);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) != 0);
+ g_assert((status & I2SR_RXAK) == 0);
+
+ /* ack the interrupt */
+ writeb(s->addr + I2SR_ADDR, 0);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) == 0);
+
+ while (size < len) {
+ /* check we are still busy */
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IBB) != 0);
+
+ /* write the data */
+ writeb(s->addr + I2DR_ADDR, buf[size]);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) != 0);
+ g_assert((status & I2SR_RXAK) == 0);
+
+ /* ack the interrupt */
+ writeb(s->addr + I2SR_ADDR, 0);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) == 0);
+
+ size++;
+ }
+
+ /* release the bus */
+ data &= ~(I2CR_MSTA | I2CR_MTX);
+ writeb(s->addr + I2CR_ADDR, data);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IBB) == 0);
+}
+
+static void imx_i2c_recv(I2CAdapter *i2c, uint8_t addr,
+ uint8_t *buf, uint16_t len)
+{
+ IMXI2C *s = (IMXI2C *)i2c;
+ uint8_t data;
+ uint8_t status;
+ uint16_t size = 0;
+
+ if (!len) {
+ return;
+ }
+
+ /* set the bus for write */
+ data = I2CR_IEN |
+ I2CR_IIEN |
+ I2CR_MSTA |
+ I2CR_MTX |
+ I2CR_TXAK;
+
+ writeb(s->addr + I2CR_ADDR, data);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IBB) != 0);
+
+ /* set the slave address */
+ imx_i2c_set_slave_addr(s, addr, IMX_I2C_READ);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) != 0);
+ g_assert((status & I2SR_RXAK) == 0);
+
+ /* ack the interrupt */
+ writeb(s->addr + I2SR_ADDR, 0);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) == 0);
+
+ /* set the bus for read */
+ data &= ~I2CR_MTX;
+ /* if only one byte don't ack */
+ if (len != 1) {
+ data &= ~I2CR_TXAK;
+ }
+ writeb(s->addr + I2CR_ADDR, data);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IBB) != 0);
+
+ /* dummy read */
+ readb(s->addr + I2DR_ADDR);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) != 0);
+
+ /* ack the interrupt */
+ writeb(s->addr + I2SR_ADDR, 0);
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) == 0);
+
+ while (size < len) {
+ /* check we are still busy */
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IBB) != 0);
+
+ if (size == (len - 1)) {
+ /* stop the read transaction */
+ data &= ~(I2CR_MSTA | I2CR_MTX);
+ } else {
+ /* ack the data read */
+ data |= I2CR_TXAK;
+ }
+ writeb(s->addr + I2CR_ADDR, data);
+
+ /* read the data */
+ buf[size] = readb(s->addr + I2DR_ADDR);
+
+ if (size != (len - 1)) {
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) != 0);
+
+ /* ack the interrupt */
+ writeb(s->addr + I2SR_ADDR, 0);
+ }
+
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IIF) == 0);
+
+ size++;
+ }
+
+ status = readb(s->addr + I2SR_ADDR);
+ g_assert((status & I2SR_IBB) == 0);
+}
+
+I2CAdapter *imx_i2c_create(uint64_t addr)
+{
+ IMXI2C *s = g_malloc0(sizeof(*s));
+ I2CAdapter *i2c = (I2CAdapter *)s;
+
+ s->addr = addr;
+
+ i2c->send = imx_i2c_send;
+ i2c->recv = imx_i2c_recv;
+
+ return i2c;
+}
diff --git a/tests/libqos/i2c.h b/tests/libqos/i2c.h
index 1ce9af4..c21f1dc 100644
--- a/tests/libqos/i2c.h
+++ b/tests/libqos/i2c.h
@@ -27,4 +27,7 @@ void i2c_recv(I2CAdapter *i2c, uint8_t addr,
/* libi2c-omap.c */
I2CAdapter *omap_i2c_create(uint64_t addr);
+/* libi2c-imx.c */
+I2CAdapter *imx_i2c_create(uint64_t addr);
+
#endif
--
2.1.4
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH v8 01/11] i.MX: Split the i.MX serial driver into a header file and a source file
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 01/11] i.MX: Split the i.MX serial driver into a header file and a source file Jean-Christophe Dubois
@ 2015-06-30 7:04 ` Peter Crosthwaite
0 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2015-06-30 7:04 UTC (permalink / raw)
To: Jean-Christophe Dubois; +Cc: qemu-devel@nongnu.org Developers
On Mon, Jun 29, 2015 at 1:11 PM, Jean-Christophe Dubois
<jcd@tribudubois.net> wrote:
> Also adding a "realise" callback.
>
> This is to prepare to accomodate the SOC requirements.
>
You have also done a significant code style sweep. I would suggest
doing a git add -p and split this into 3 patches:
1: Style cleanups
2: Header movement
3: realize
The hunks look pretty self contained so it should be churn free.
Perhaps do the style cleanup last so there are no "you missed a bit"
for style issues in header-movement/realize changes.
Regards,
Peter
> Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
> ---
>
> Changes since v1:
> * not present on v1
>
> Changes since v2:
> * not present on v2
>
> Changes since v3:
> * not present on v3
>
> Changes since v4:
> * not present on v4
>
> Changes since v5:
> * not present on v5
>
> Changes since v6:
> * not present on v6
>
> Changes since v7:
> * Splited the i.MX serial emulator into a header file and a source file
>
> hw/char/imx_serial.c | 176 +++++++++++--------------------------------
> include/hw/char/imx_serial.h | 104 +++++++++++++++++++++++++
> 2 files changed, 149 insertions(+), 131 deletions(-)
> create mode 100644 include/hw/char/imx_serial.h
>
> diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
> index f3fbc77..8c2d071 100644
> --- a/hw/char/imx_serial.c
> +++ b/hw/char/imx_serial.c
> @@ -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,16 +18,14 @@
> * 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"
>
> //#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 +37,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 +61,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;
> @@ -242,13 +163,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;
> @@ -298,25 +219,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 +265,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);
> }
> }
>
> @@ -377,22 +298,18 @@ static void imx_event(void *opaque, int event)
> }
> }
>
> -
> static const struct MemoryRegionOps imx_serial_ops = {
> .read = imx_serial_read,
> .write = imx_serial_write,
> .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);
> + /* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
> + s->chr = qemu_char_get_next_serial();
>
> if (s->chr) {
> qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
> @@ -401,45 +318,42 @@ 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)
> {
> DeviceState *dev;
> SysBusDevice *bus;
> - CharDriverState *chr;
> - const char chr_name[] = "serial";
> - char label[ARRAY_SIZE(chr_name) + 1];
> -
> - dev = qdev_create(NULL, TYPE_IMX_SERIAL);
>
> if (uart >= MAX_SERIAL_PORTS) {
> hw_error("Cannot assign uart %d: QEMU supports only %d ports\n",
> uart, MAX_SERIAL_PORTS);
> }
> - chr = serial_hds[uart];
> - if (!chr) {
> - snprintf(label, ARRAY_SIZE(label), "%s%d", chr_name, uart);
> - chr = qemu_chr_new(label, "null", NULL);
> - if (!(chr)) {
> - hw_error("Can't assign serial port to imx-uart%d.\n", uart);
> - }
> - }
>
> - qdev_prop_set_chr(dev, "chardev", chr);
> + dev = qdev_create(NULL, TYPE_IMX_SERIAL);
> +
> bus = SYS_BUS_DEVICE(dev);
> qdev_init_nofail(dev);
> +
> if (addr != (hwaddr)-1) {
> sysbus_mmio_map(bus, 0, addr);
> }
> - sysbus_connect_irq(bus, 0, irq);
>
> + sysbus_connect_irq(bus, 0, irq);
> }
>
> -
> -static Property imx32_serial_properties[] = {
> +static Property imx_serial_properties[] = {
> DEFINE_PROP_CHR("chardev", IMXSerialState, chr),
> DEFINE_PROP_END_OF_LIST(),
> };
> @@ -447,21 +361,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;
> + set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
> }
>
> 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)
> diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
> new file mode 100644
> index 0000000..dba0cbb
> --- /dev/null
> +++ b/include/hw/char/imx_serial.h
> @@ -0,0 +1,104 @@
> +/*
> + * 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;
> +
> +void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq);
> +
> +#endif
> --
> 2.1.4
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH v8 02/11] i.MX: Split the i.MX AVIC emulator into a header file and a source file
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 02/11] i.MX: Split the i.MX AVIC emulator " Jean-Christophe Dubois
@ 2015-06-30 7:05 ` Peter Crosthwaite
0 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2015-06-30 7:05 UTC (permalink / raw)
To: Jean-Christophe Dubois; +Cc: qemu-devel@nongnu.org Developers
On Mon, Jun 29, 2015 at 1:11 PM, Jean-Christophe Dubois
<jcd@tribudubois.net> wrote:
> This is to prepare to accomodate the SOC requirements.
>
Same but only 2, one for style, one for headering.
Regards,
Peter
> Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
> ---
>
> Changes since v1:
> * not present on v1
>
> Changes since v2:
> * not present on v2
>
> Changes since v3:
> * not present on v3
>
> Changes since v4:
> * not present on v4
>
> Changes since v5:
> * not present on v5
>
> Changes since v6:
> * not present on v6
>
> Changes since v7:
> * Splited the i.MX AVIC emulator into a header file and a source file
>
> hw/intc/imx_avic.c | 56 +++++++++-------------------------------------
> include/hw/intc/imx_avic.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 66 insertions(+), 46 deletions(-)
> create mode 100644 include/hw/intc/imx_avic.h
>
> diff --git a/hw/intc/imx_avic.c b/hw/intc/imx_avic.c
> index e48f66c..96c376b 100644
> --- a/hw/intc/imx_avic.c
> +++ b/hw/intc/imx_avic.c
> @@ -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);
> diff --git a/include/hw/intc/imx_avic.h b/include/hw/intc/imx_avic.h
> new file mode 100644
> index 0000000..1645ba6
> --- /dev/null
> +++ b/include/hw/intc/imx_avic.h
> @@ -0,0 +1,56 @@
> +/*
> + * 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 {
> + /*< 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
> --
> 2.1.4
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH v8 04/11] i.MX: Split the i.MX EPIT emulator into a header file and a source file.
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 04/11] i.MX: Split the i.MX EPIT " Jean-Christophe Dubois
@ 2015-06-30 7:12 ` Peter Crosthwaite
0 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2015-06-30 7:12 UTC (permalink / raw)
To: Jean-Christophe Dubois; +Cc: qemu-devel@nongnu.org Developers
On Mon, Jun 29, 2015 at 1:11 PM, Jean-Christophe Dubois
<jcd@tribudubois.net> wrote:
> This is to prepare to accomodate the SOC requirements.
>
> Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
> ---
>
> Changes since v1:
> * not present on v1
>
> Changes since v2:
> * not present on v2
>
> Changes since v3:
> * not present on v3
>
> Changes since v4:
> * not present on v4
>
> Changes since v5:
> * not present on v5
>
> Changes since v6:
> * not present on v6
>
> Changes since v7:
> * Splited the i.MX EPIT emulator into a header file and a source file
>
> hw/timer/imx_epit.c | 65 +++++------------------------------
> include/hw/timer/imx_epit.h | 83 +++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 92 insertions(+), 56 deletions(-)
> create mode 100644 include/hw/timer/imx_epit.h
>
> diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
> index ffefc22..39fc3f1 100644
> --- a/hw/timer/imx_epit.c
> +++ b/hw/timer/imx_epit.c
> @@ -5,23 +5,17 @@
> * 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 +55,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 +66,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 +127,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 +297,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[]) {
> diff --git a/include/hw/timer/imx_epit.h b/include/hw/timer/imx_epit.h
> new file mode 100644
> index 0000000..dbc99ca
> --- /dev/null
> +++ b/include/hw/timer/imx_epit.h
> @@ -0,0 +1,83 @@
> +/*
> + * 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 {
> + /* <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;
> +
> +void imx_timerp_create(const hwaddr addr,
> + qemu_irq irq,
> + DeviceState *ccm);
> +
Qdev construction helpers are depracated in favor of just inlining the
qdev_creation process in the machine model. Since this is pre-existing
though, I would just leave it in imx.h.
Regards,
Peter
> +#endif /* IMX_EPIT_H */
> --
> 2.1.4
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH v8 06/11] kzm: Use modified i.MX emulators.
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 06/11] kzm: Use modified i.MX emulators Jean-Christophe Dubois
@ 2015-06-30 7:12 ` Peter Crosthwaite
0 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2015-06-30 7:12 UTC (permalink / raw)
To: Jean-Christophe Dubois; +Cc: qemu-devel@nongnu.org Developers
On Mon, Jun 29, 2015 at 1:12 PM, Jean-Christophe Dubois
<jcd@tribudubois.net> wrote:
> Use modified AVIC, CCM, UART, GPT, EPIT emultors.
>
"emulators"
> Tested by booting Linux one KZM emulator.
>
"on"?
> Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
> ---
>
> Changes since v1:
> * not present on v1
>
> Changes since v2:
> * not present on v2
>
> Changes since v3:
> * not present on v3
>
> Changes since v4:
> * not present on v4
>
> Changes since v5:
> * not present on v5
>
> Changes since v6:
> * not present on v6
>
> Changes since v7:
> * update KZM target to use new emulators
>
> hw/arm/kzm.c | 86 +++++++++++++++++++++++++++-------------------------
> include/hw/arm/imx.h | 34 ---------------------
> 2 files changed, 45 insertions(+), 75 deletions(-)
> delete mode 100644 include/hw/arm/imx.h
>
> diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
> index 5be0369..485e745 100644
> --- a/hw/arm/kzm.c
> +++ b/hw/arm/kzm.c
> @@ -22,45 +22,49 @@
> #include "sysemu/sysemu.h"
> #include "hw/boards.h"
> #include "hw/char/serial.h"
> -#include "hw/arm/imx.h"
> -
> - /* Memory map for Kzm Emulation Baseboard:
> - * 0x00000000-0x00003fff 16k secure ROM IGNORED
> - * 0x00004000-0x00407fff Reserved IGNORED
> - * 0x00404000-0x00407fff ROM IGNORED
> - * 0x00408000-0x0fffffff Reserved IGNORED
> - * 0x10000000-0x1fffbfff RAM aliasing IGNORED
> - * 0x1fffc000-0x1fffffff RAM EMULATED
> - * 0x20000000-0x2fffffff Reserved IGNORED
> - * 0x30000000-0x7fffffff I.MX31 Internal Register Space
> - * 0x43f00000 IO_AREA0
> - * 0x43f90000 UART1 EMULATED
> - * 0x43f94000 UART2 EMULATED
> - * 0x68000000 AVIC EMULATED
> - * 0x53f80000 CCM EMULATED
> - * 0x53f94000 PIT 1 EMULATED
> - * 0x53f98000 PIT 2 EMULATED
> - * 0x53f90000 GPT EMULATED
> - * 0x80000000-0x87ffffff RAM EMULATED
> - * 0x88000000-0x8fffffff RAM Aliasing EMULATED
> - * 0xa0000000-0xafffffff NAND Flash IGNORED
> - * 0xb0000000-0xb3ffffff Unavailable IGNORED
> - * 0xb4000000-0xb4000fff 8-bit free space IGNORED
> - * 0xb4001000-0xb400100f Board control IGNORED
> - * 0xb4001003 DIP switch
> - * 0xb4001010-0xb400101f 7-segment LED IGNORED
> - * 0xb4001020-0xb400102f LED IGNORED
> - * 0xb4001030-0xb400103f LED IGNORED
> - * 0xb4001040-0xb400104f FPGA, UART EMULATED
> - * 0xb4001050-0xb400105f FPGA, UART EMULATED
> - * 0xb4001060-0xb40fffff FPGA IGNORED
> - * 0xb6000000-0xb61fffff LAN controller EMULATED
> - * 0xb6200000-0xb62fffff FPGA NAND Controller IGNORED
> - * 0xb6300000-0xb7ffffff Free IGNORED
> - * 0xb8000000-0xb8004fff Memory control registers IGNORED
> - * 0xc0000000-0xc3ffffff PCMCIA/CF IGNORED
> - * 0xc4000000-0xffffffff Reserved IGNORED
> - */
> +#include "hw/misc/imx_ccm.h"
> +#include "hw/intc/imx_avic.h"
> +#include "hw/timer/imx_epit.h"
> +#include "hw/timer/imx_gpt.h"
> +#include "hw/char/imx_serial.h"
> +
> +/* Memory map for Kzm Emulation Baseboard:
> + * 0x00000000-0x00003fff 16k secure ROM IGNORED
> + * 0x00004000-0x00407fff Reserved IGNORED
> + * 0x00404000-0x00407fff ROM IGNORED
> + * 0x00408000-0x0fffffff Reserved IGNORED
> + * 0x10000000-0x1fffbfff RAM aliasing IGNORED
> + * 0x1fffc000-0x1fffffff RAM EMULATED
> + * 0x20000000-0x2fffffff Reserved IGNORED
> + * 0x30000000-0x7fffffff I.MX31 Internal Register Space
> + * 0x43f00000 IO_AREA0
> + * 0x43f90000 UART1 EMULATED
> + * 0x43f94000 UART2 EMULATED
> + * 0x68000000 AVIC EMULATED
> + * 0x53f80000 CCM EMULATED
> + * 0x53f94000 PIT 1 EMULATED
> + * 0x53f98000 PIT 2 EMULATED
> + * 0x53f90000 GPT EMULATED
> + * 0x80000000-0x87ffffff RAM EMULATED
> + * 0x88000000-0x8fffffff RAM Aliasing EMULATED
> + * 0xa0000000-0xafffffff NAND Flash IGNORED
> + * 0xb0000000-0xb3ffffff Unavailable IGNORED
> + * 0xb4000000-0xb4000fff 8-bit free space IGNORED
> + * 0xb4001000-0xb400100f Board control IGNORED
> + * 0xb4001003 DIP switch
> + * 0xb4001010-0xb400101f 7-segment LED IGNORED
> + * 0xb4001020-0xb400102f LED IGNORED
> + * 0xb4001030-0xb400103f LED IGNORED
> + * 0xb4001040-0xb400104f FPGA, UART EMULATED
> + * 0xb4001050-0xb400105f FPGA, UART EMULATED
> + * 0xb4001060-0xb40fffff FPGA IGNORED
> + * 0xb6000000-0xb61fffff LAN controller EMULATED
> + * 0xb6200000-0xb62fffff FPGA NAND Controller IGNORED
> + * 0xb6300000-0xb7ffffff Free IGNORED
> + * 0xb8000000-0xb8004fff Memory control registers IGNORED
> + * 0xc0000000-0xc3ffffff PCMCIA/CF IGNORED
> + * 0xc4000000-0xffffffff Reserved IGNORED
> + */
>
Split off style sweep, although this one may be not worth it. Out of
scope style changes do reduce the utility of git-blame so unless they
are local to, or prepare for a functional change they are discouraged.
Regards,
Peter
> #define KZM_RAMADDRESS (0x80000000)
> #define KZM_FPGA (0xb4001040)
> @@ -106,7 +110,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 +118,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);
> diff --git a/include/hw/arm/imx.h b/include/hw/arm/imx.h
> deleted file mode 100644
> index ea9e093..0000000
> --- a/include/hw/arm/imx.h
> +++ /dev/null
> @@ -1,34 +0,0 @@
> -/*
> - * i.MX31 emulation
> - *
> - * Copyright (C) 2012 Peter Chubb
> - * NICTA
> - *
> - * This code is released under the GPL, version 2.0 or later
> - * See the file `../COPYING' for details.
> - */
> -
> -#ifndef IMX_H
> -#define IMX_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);
> -void imx_timerg_create(const hwaddr addr,
> - qemu_irq irq,
> - DeviceState *ccm);
> -
> -
> -#endif /* IMX_H */
> --
> 2.1.4
>
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [Qemu-devel] [PATCH v8 09/11] i.MX25: Add the i.MX25 SOC support
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 09/11] i.MX25: Add the i.MX25 SOC support Jean-Christophe Dubois
@ 2015-06-30 7:29 ` Peter Crosthwaite
0 siblings, 0 replies; 17+ messages in thread
From: Peter Crosthwaite @ 2015-06-30 7:29 UTC (permalink / raw)
To: Jean-Christophe Dubois; +Cc: qemu-devel@nongnu.org Developers
On Mon, Jun 29, 2015 at 1:12 PM, Jean-Christophe Dubois
<jcd@tribudubois.net> wrote:
> For now we do support the foolowing devices:
> * GPT timers (from i.MX31)
> * EPIT timers (from i.MX31)
> * CCM (from i.MX31)
> * AVIC (from i.MX31)
> * UART (from i.MX31)
> * Ethernet FEC port
> * I2C controller
>
> Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
> ---
>
> Changes since v1:
> * not present on v1
>
> Changes since v2:
> * not present on v2
>
> Changes since v3:
> * not present on v3
>
> Changes since v4:
> * not present on v4
>
> Changes since v5:
> * not present on v5
>
> Changes since v6:
> * not present on v6
>
> Changes since v7:
> * Added a SOC specific file for i.MX25
>
> default-configs/arm-softmmu.mak | 1 +
> hw/arm/Makefile.objs | 1 +
> hw/arm/fsl-imx25.c | 304 ++++++++++++++++++++++++++++++++++++++++
> include/hw/arm/fsl-imx25.h | 52 +++++++
> 4 files changed, 358 insertions(+)
> create mode 100644 hw/arm/fsl-imx25.c
> create mode 100644 include/hw/arm/fsl-imx25.h
>
> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> index c6f509d..057f39c 100644
> --- a/default-configs/arm-softmmu.mak
> +++ b/default-configs/arm-softmmu.mak
> @@ -99,6 +99,7 @@ CONFIG_ALLWINNER_A10_PIT=y
> CONFIG_ALLWINNER_A10_PIC=y
> CONFIG_ALLWINNER_A10=y
>
> +CONFIG_FSL_IMX25=y
> CONFIG_IMX_I2C=y
>
> CONFIG_XIO3130=y
> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> index cf346c1..b89c31d 100644
> --- a/hw/arm/Makefile.objs
> +++ b/hw/arm/Makefile.objs
> @@ -13,3 +13,4 @@ obj-y += omap1.o omap2.o strongarm.o
> obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
> obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
> obj-$(CONFIG_XLNX_ZYNQMP) += xlnx-zynqmp.o xlnx-ep108.o
> +obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o
> diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
> new file mode 100644
> index 0000000..b2db548
> --- /dev/null
> +++ b/hw/arm/fsl-imx25.c
> @@ -0,0 +1,304 @@
> +/*
> + * Copyright (c) 2013 Jean-Christophe Dubois <jcd@tribudubois.net>
> + *
> + * i.MX25 SOC emulation.
> + *
> + * Based on hw/arm/xlnx-zynqmp.c
> + *
> + * Copyright (C) 2015 Xilinx Inc
> + * Written by Peter Crosthwaite <peter.crosthwaite@xilinx.com>
> + *
You probably don't need this if you are just borrowing template.
> + * 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/>.
> + */
> +
> +#include "hw/arm/fsl-imx25.h"
> +#include "sysemu/sysemu.h"
> +
> +/* Memory map for 3D-Stack Emulation Baseboard:
> + * 0x00000000-0x00003fff 16k ROM IGNORED
> + * 0x00004000-0x00403fff Reserved IGNORED
> + * 0x00404000-0x00408fff 20k ROM IGNORED
> + * 0x00409000-0x0fffffff Reserved IGNORED
> + * 0x10000000-0x1fffffff Reserved IGNORED
> + * 0x20000000-0x2fffffff Reserved IGNORED
> + * 0x30000000-0x3fffffff Reserved IGNORED
> + * 0x40000000-0x43efffff Reserved IGNORED
> + * 0x43f00000-0x6fffffff I.MX25 Internal Register Space
> + * 0x43f00000 IO_AREA0
> + * 0x43f80000 I2C0 EMULATED
> + * 0x43f84000 I2C2 EMULATED
> + * 0x43f98000 I2C1 EMULATED
> + * 0x43f90000 UART1 EMULATED
> + * 0x43f94000 UART2 EMULATED
> + * 0x43fb0000 UART4 IGNORED
> + * 0x43fb4000 UART5 IGNORED
> + * 0x5000c000 UART3 EMULATED
> + * 0x50038000 FEC EMULATED
> + * 0x53f80000 CCM EMULATED
> + * 0x53f84000 GPT 4 EMULATED
So the ones thare are use by the code should just be #defines. This
eliminates repetition of the literal constants in the mmio mappings..
#define GPT_4_ADDR 0x53f83000 /* EMULATED */
For consistency I would just convert the whole table, even the ignored devs.
> + * 0x53f88000 GPT 3 EMULATED
> + * 0x53f8c000 GPT 2 EMULATED
> + * 0x53f90000 GPT 1 EMULATED
> + * 0x53f94000 PIT 1 EMULATED
> + * 0x53f98000 PIT 2 EMULATED
> + * 0x53f9c000 GPIO-4 EMULATED
> + * 0x53fa4000 GPIO-3 EMULATED
> + * 0x53fcc000 GPIO-1 EMULATED
> + * 0x53fd0000 GPIO-2 EMULATED
> + * 0x68000000 ASIC EMULATED
> + * 0x78000000-0x7801ffff SRAM EMULATED
> + * 0x78020000-0x7fffffff SRAM Aliasing EMULATED
> + * 0x80000000-0x87ffffff RAM + Alias EMULATED
> + * 0x90000000-0x9fffffff RAM + Alias EMULATED
> + * 0xa0000000-0xa7ffffff Flash IGNORED
> + * 0xa8000000-0xafffffff Flash IGNORED
> + * 0xb0000000-0xb1ffffff SRAM IGNORED
> + * 0xb2000000-0xb3ffffff SRAM IGNORED
> + * 0xb4000000-0xb5ffffff CS4 IGNORED
> + * 0xb6000000-0xb8000fff Reserved IGNORED
> + * 0xb8001000-0xb8001fff SDRAM CTRL reg IGNORED
> + * 0xb8002000-0xb8002fff WEIM CTRL reg IGNORED
> + * 0xb8003000-0xb8003fff M3IF CTRL reg IGNORED
> + * 0xb8004000-0xb8004fff EMI CTRL reg IGNORED
> + * 0xb8005000-0xbaffffff Reserved IGNORED
> + * 0xbb000000-0xbb000fff NAND flash area buf IGNORED
> + * 0xbb001000-0xbb0011ff NAND flash reserved IGNORED
> + * 0xbb001200-0xbb001dff Reserved IGNORED
> + * 0xbb001e00-0xbb001fff NAN flash CTRL reg IGNORED
> + * 0xbb012000-0xbfffffff Reserved IGNORED
> + * 0xc0000000-0xffffffff Reserved IGNORED
> + */
> +
> +static void fsl_imx25_init(Object *obj)
> +{
> + FslImx25State *s = FSL_IMX25(obj);
> + int i;
> +
> + object_initialize(&s->cpu, sizeof(s->cpu), "arm926-" TYPE_ARM_CPU);
> +
> + object_initialize(&s->avic, sizeof(s->avic), TYPE_IMX_AVIC);
> + qdev_set_parent_bus(DEVICE(&s->avic), sysbus_get_default());
> +
> + object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX_CCM);
> + qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default());
> +
> + for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
> + if (i >= MAX_SERIAL_PORTS) {
> + break;
> + }
> + object_initialize(&s->uart[i], sizeof(s->uart[i]), TYPE_IMX_SERIAL);
> + qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus_get_default());
> + }
> +
> + for (i = 0; i < FSL_IMX25_NUM_GPTS; i++) {
> + object_initialize(&s->gpt[i], sizeof(s->gpt[i]), TYPE_IMX_GPT);
> + qdev_set_parent_bus(DEVICE(&s->gpt[i]), sysbus_get_default());
> + }
> +
> + for (i = 0; i < FSL_IMX25_NUM_EPITS; i++) {
> + object_initialize(&s->epit[i], sizeof(s->epit[i]), TYPE_IMX_EPIT);
> + qdev_set_parent_bus(DEVICE(&s->epit[i]), sysbus_get_default());
> + }
> +
> + object_initialize(&s->fec, sizeof(s->fec), TYPE_IMX_FEC);
> + qdev_set_parent_bus(DEVICE(&s->fec), sysbus_get_default());
> +
> + for (i = 0; i < FSL_IMX25_NUM_I2CS; i++) {
> + object_initialize(&s->i2c[i], sizeof(s->i2c[i]), TYPE_IMX_I2C);
> + qdev_set_parent_bus(DEVICE(&s->i2c[i]), sysbus_get_default());
> + }
> +}
> +
> +static void fsl_imx25_realize(DeviceState *dev, Error **errp)
> +{
> + FslImx25State *s = FSL_IMX25(dev);
> + //MemoryRegion *system_memory = get_system_memory();
Remove commented code. (does checkpatch catch this due to CPP comment?)
> + uint8_t i;
> + Error *err = NULL;
> +
> + /* Initialize the CPU */
Code is self documentating, you can drop these. I would drop most of
them except in cases where the code is irrugular, unusual or tricky in
some way.
> + object_property_set_bool(OBJECT(&s->cpu), true, "realized", &err);
> + if (err) {
> + error_propagate((errp), (err));
> + return;
> + }
> +
> + /* Initialize the PIC */
> + object_property_set_bool(OBJECT(&s->avic), true, "realized", &err);
> + if (err) {
> + error_propagate((errp), (err));
> + return;
> + }
> + /* Connect the PIC interrupt to the CPU */
This comment ...
> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->avic), 0, 0x68000000);
Should go here.
> + sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 0,
> + qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_IRQ));
> + sysbus_connect_irq(SYS_BUS_DEVICE(&s->avic), 1,
> + qdev_get_gpio_in(DEVICE(&s->cpu), ARM_CPU_FIQ));
> +
> + /* Initialize the CCM */
> + object_property_set_bool(OBJECT(&s->ccm), true, "realized", &err);
> + if (err) {
> + error_propagate((errp), (err));
> + return;
> + }
> + /* Map CCM memory */
> + sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, 0x53f80000);
> +
Constants can be replaced with the macro defs.
> + /* Initialize all UARTS */
> + for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
> + static const struct {
> + hwaddr addr;
> + unsigned int irq;
> + } serial_table[FSL_IMX25_NUM_UARTS] = {
> + { 0x43f90000, 45 },
> + { 0x43f94000, 32 },
> + { 0x5000c000, 18 },
> + { 0x50008000, 5 },
> + { 0x5002c000, 40 }
And the same.
Alternatively, zynqmp defines these tables up top of the files as
static const. This is to avoid the need for a memory map comment. You
could do the same, pulling these tables up top to replace relevant
sections of the comment.
> + };
> +
> + /* Bail out if we exeeded Qemu UART count */
"exceeded" "QEMU"
Regards,
Peter
> + if (i >= MAX_SERIAL_PORTS) {
> + break;
> + }
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2015-06-30 7:29 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-06-29 20:11 [Qemu-devel] [PATCH v8 00/11] i.MX: Add i.MX25 support through the 3DS evaluation board Jean-Christophe Dubois
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 01/11] i.MX: Split the i.MX serial driver into a header file and a source file Jean-Christophe Dubois
2015-06-30 7:04 ` Peter Crosthwaite
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 02/11] i.MX: Split the i.MX AVIC emulator " Jean-Christophe Dubois
2015-06-30 7:05 ` Peter Crosthwaite
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 03/11] i.MX: Split the i.MX CCM " Jean-Christophe Dubois
2015-06-29 20:11 ` [Qemu-devel] [PATCH v8 04/11] i.MX: Split the i.MX EPIT " Jean-Christophe Dubois
2015-06-30 7:12 ` Peter Crosthwaite
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 05/11] i.MX: Split the i.MX GPT " Jean-Christophe Dubois
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 06/11] kzm: Use modified i.MX emulators Jean-Christophe Dubois
2015-06-30 7:12 ` Peter Crosthwaite
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 07/11] i.MX: Add FEC Ethernet Emulator Jean-Christophe Dubois
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 08/11] i.MX: Add I2C controller emulator Jean-Christophe Dubois
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 09/11] i.MX25: Add the i.MX25 SOC support Jean-Christophe Dubois
2015-06-30 7:29 ` Peter Crosthwaite
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 10/11] i.MX25: Add support for the i.MX25 PDK 3DS Jean-Christophe Dubois
2015-06-29 20:12 ` [Qemu-devel] [PATCH v8 11/11] i.MX: Add qtest support for I2C device emulator Jean-Christophe Dubois
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).