[Qemu-devel] [PATCH] util/path: Always translate /etc/ld.so.cache

2017-01-27 Thread Andrey Smirnov
Always translate /etc/ld.so.cache to point somwhere inside of guest's
filesystem tree pointed to by 'prefix'. This prevents guest's libc from
reading /etc/ld.so.cache of the host and potentialy failing. One of the
manifestation of the problem could be easily reproduced by executing and
simple application compiled for PowerPC on a x86 host using
linux-use/qemu-ppc emulation.

Anything as simple as:

 qemu-ppc -L  /bin/ls

should trigger the problem.

Signed-off-by: Andrey Smirnov 
---
 util/path.c | 53 +
 1 file changed, 49 insertions(+), 4 deletions(-)

diff --git a/util/path.c b/util/path.c
index 5479f76..cc28bff 100644
--- a/util/path.c
+++ b/util/path.c
@@ -108,8 +108,8 @@ static void set_parents(struct pathelem *child, struct 
pathelem *parent)
 }
 
 /* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */
-static const char *
-follow_path(const struct pathelem *cursor, const char *name)
+static struct pathelem *
+follow_path(struct pathelem *cursor, const char *name)
 {
 unsigned int i, namelen;
 
@@ -117,7 +117,7 @@ follow_path(const struct pathelem *cursor, const char *name)
 namelen = strcspn(name, "/");
 
 if (namelen == 0)
-return cursor->pathname;
+return cursor;
 
 if (strneq(name, namelen, ".."))
 return follow_path(cursor->parent, name + namelen);
@@ -133,9 +133,28 @@ follow_path(const struct pathelem *cursor, const char 
*name)
 return NULL;
 }
 
+
+static void append_entry(struct pathelem *cursor,
+ const char *name, unsigned type)
+{
+size_t i;
+struct pathelem *parent;
+
+parent = cursor->parent;
+
+for (i = 0; i < parent->num_entries; i++) {
+if (parent->entries[i] == cursor) {
+break;
+}
+}
+
+parent->entries[i] = add_entry(cursor, name, type);
+}
+
 void init_paths(const char *prefix)
 {
 char pref_buf[PATH_MAX];
+struct pathelem *cursor;
 
 if (prefix[0] == '\0' ||
 !strcmp(prefix, "/"))
@@ -164,15 +183,41 @@ void init_paths(const char *prefix)
 } else {
 set_parents(base, base);
 }
+
+/*
+ * libc does not necessarily handle reading host's ld.so.cache
+ * well (e.g. running PowerPC code on x86, or, very likely any
+ * mixed endian combination)
+ *
+ * So check if guest's prefix "tree" provides ld.so.cache and if
+ * not add a fake translation entry, so as to prevent guest's libc
+ * request to /etc/ld.so.cache to resolve into host's
+ * /etc/ld.so.cache
+ */
+cursor = follow_path(base, "/etc/ld.so.cache");
+if (!cursor) {
+cursor = follow_path(base, "/etc/");
+if (!cursor) {
+cursor = follow_path(base, "/");
+append_entry(cursor, "etc", DT_DIR);
+cursor = follow_path(base, "/etc/");
+}
+
+append_entry(cursor, "ld.so.cache", DT_REG);
+}
 }
 
 /* Look for path in emulation dir, otherwise return name. */
 const char *path(const char *name)
 {
+struct pathelem *cursor;
+
 /* Only do absolute paths: quick and dirty, but should mostly be OK.
Could do relative by tracking cwd. */
 if (!base || !name || name[0] != '/')
 return name;
 
-return follow_path(base, name) ?: name;
+cursor = follow_path(base, name);
+
+return cursor ? cursor->pathname : name;
 }
-- 
2.9.3




Re: [Qemu-devel] [PATCH] util/path: Always translate /etc/ld.so.cache

2017-01-27 Thread Andrey Smirnov
On Fri, Jan 27, 2017 at 10:53 AM, Peter Maydell
 wrote:
> On 27 January 2017 at 18:31, Andrey Smirnov  wrote:
>> Always translate /etc/ld.so.cache to point somwhere inside of guest's
>> filesystem tree pointed to by 'prefix'. This prevents guest's libc from
>> reading /etc/ld.so.cache of the host and potentialy failing. One of the
>> manifestation of the problem could be easily reproduced by executing and
>> simple application compiled for PowerPC on a x86 host using
>> linux-use/qemu-ppc emulation.
>>
>> Anything as simple as:
>>
>>      qemu-ppc -L  /bin/ls
>>
>> should trigger the problem.
>>
>> Signed-off-by: Andrey Smirnov 
>
> Have you tested that this doesn't cause execution inside a chroot
> to behave wrongly (in a chroot, the host fs /etc/ld.so.cache is
> definitely the one you want to use) ?

No, I have not. I'll go back and do more homework. Just to make sure
that my assumptions are correct, I consider "qemu-ppc -L" and
"chroot  qemu-ppc" to be the only use-cases supported, and
"chroot  qemu-ppc -L " is not something that is expected to
work correctly. Is that a correct assumption to make?

>
> (glibc really ought to fix their ld.so.cache reading bugs.)
>

I agree. I am planning on taking a look at the glibc side of things to
see if there's a simple way to fix the problem there, but in the
meantime I thought it would be good to float this patch and get some
feedback.

Cheers!

Andrey Smirnov



[Qemu-devel] [RFC PATCH] armv7m_nvic: Use qemu_get_cpu(0) instead of current_cpu

2016-06-28 Thread Andrey Smirnov
Starting QEMU with -S results in current_cpu containing its initial
value of NULL. It is however possible to connect to such QEMU instance
and query various CPU registers, one example being CPUID, and doing that
results in QEMU segfaulting.

Using qemu_get_cpu(0) seem reasonable enough given that ARMv7M
architecture is a single core architecture.

Signed-off-by: Andrey Smirnov 
---
 hw/intc/armv7m_nvic.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
index 890d5d7..06d8db6 100644
--- a/hw/intc/armv7m_nvic.c
+++ b/hw/intc/armv7m_nvic.c
@@ -187,11 +187,11 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
 case 0x1c: /* SysTick Calibration Value.  */
 return 1;
 case 0xd00: /* CPUID Base.  */
-cpu = ARM_CPU(current_cpu);
+cpu = ARM_CPU(qemu_get_cpu(0));
 return cpu->midr;
 case 0xd04: /* Interrupt Control State.  */
 /* VECTACTIVE */
-cpu = ARM_CPU(current_cpu);
+cpu = ARM_CPU(qemu_get_cpu(0));
 val = cpu->env.v7m.exception;
 if (val == 1023) {
 val = 0;
@@ -222,7 +222,7 @@ static uint32_t nvic_readl(nvic_state *s, uint32_t offset)
 val |= (1 << 31);
 return val;
 case 0xd08: /* Vector Table Offset.  */
-cpu = ARM_CPU(current_cpu);
+cpu = ARM_CPU(qemu_get_cpu(0));
 return cpu->env.v7m.vecbase;
 case 0xd0c: /* Application Interrupt/Reset Control.  */
 return 0xfa05;
@@ -349,7 +349,7 @@ static void nvic_writel(nvic_state *s, uint32_t offset, 
uint32_t value)
 }
 break;
 case 0xd08: /* Vector Table Offset.  */
-cpu = ARM_CPU(current_cpu);
+cpu = ARM_CPU(qemu_get_cpu(0));
 cpu->env.v7m.vecbase = value & 0xff80;
 break;
 case 0xd0c: /* Application Interrupt/Reset Control.  */
-- 
2.5.5




[Qemu-devel] [RFC PATCH] exec: Support non-direct memory writes in cpu_memory_rw_debug

2016-06-28 Thread Andrey Smirnov
Add code to support writing to memory mapped peripherals via
cpu_memory_rw_debug(). The code of that function already supports
reading from such memory regions, so this commit makes that
functionality "symmetric".

One use-case for that functionality is setting various registers of a
non-running CPU. A concrete example would be starting QEMU emulating
Cortex-M with -S, connecting with GDB and modifying the value of Vector
Table Offset register.

Signed-off-by: Andrey Smirnov 
---
 cpus.c  |  2 +-
 disas.c |  4 ++--
 exec.c  | 57 -
 gdbstub.c   | 10 
 hw/i386/kvmvapic.c  | 18 +++---
 hw/mips/mips_jazz.c |  2 +-
 hw/pci-host/prep.c  |  2 +-
 hw/virtio/virtio.c  |  2 +-
 include/exec/cpu-all.h  |  2 +-
 include/exec/memory.h   | 15 +---
 include/exec/softmmu-semi.h | 16 ++---
 ioport.c|  6 ++---
 monitor.c   |  2 +-
 target-arm/arm-semi.c   |  2 +-
 target-arm/kvm64.c  |  8 +++
 target-i386/helper.c|  6 ++---
 target-i386/kvm.c   |  8 +++
 target-ppc/kvm.c|  8 +++
 target-s390x/kvm.c  |  8 +++
 target-xtensa/xtensa-semi.c |  6 ++---
 20 files changed, 100 insertions(+), 84 deletions(-)

diff --git a/cpus.c b/cpus.c
index 84c3520..14f0f4f 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1691,7 +1691,7 @@ void qmp_memsave(int64_t addr, int64_t size, const char 
*filename,
 l = sizeof(buf);
 if (l > size)
 l = size;
-if (cpu_memory_rw_debug(cpu, addr, buf, l, 0) != 0) {
+if (cpu_memory_rw_debug(cpu, addr, buf, l, MEMTX_READ) != 0) {
 error_setg(errp, "Invalid addr 0x%016" PRIx64 "/size %" PRId64
  " specified", orig_addr, orig_size);
 goto exit;
diff --git a/disas.c b/disas.c
index 05a7a12..8ceeedb 100644
--- a/disas.c
+++ b/disas.c
@@ -39,7 +39,7 @@ target_read_memory (bfd_vma memaddr,
 {
 CPUDebug *s = container_of(info, CPUDebug, info);
 
-cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
+cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, MEMTX_READ);
 return 0;
 }
 
@@ -358,7 +358,7 @@ monitor_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int 
length,
 if (monitor_disas_is_physical) {
 cpu_physical_memory_read(memaddr, myaddr, length);
 } else {
-cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, 0);
+cpu_memory_rw_debug(s->cpu, memaddr, myaddr, length, MEMTX_READ);
 }
 return 0;
 }
diff --git a/exec.c b/exec.c
index 0122ef7..048d3d0 100644
--- a/exec.c
+++ b/exec.c
@@ -2219,7 +2219,7 @@ static MemTxResult subpage_write(void *opaque, hwaddr 
addr,
 abort();
 }
 return address_space_write(subpage->as, addr + subpage->base,
-   attrs, buf, len);
+   attrs, buf, len, false);
 }
 
 static bool subpage_accepts(void *opaque, hwaddr addr,
@@ -2436,7 +2436,7 @@ MemoryRegion *get_system_io(void)
 /* physical memory access (slow version, mainly for debug) */
 #if defined(CONFIG_USER_ONLY)
 int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
-uint8_t *buf, int len, int is_write)
+uint8_t *buf, int len, MemTxType type)
 {
 int l, flags;
 target_ulong page;
@@ -2450,7 +2450,8 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
 flags = page_get_flags(page);
 if (!(flags & PAGE_VALID))
 return -1;
-if (is_write) {
+if (type == MEMTX_WRITE ||
+type == MEMTX_PROGRAM) {
 if (!(flags & PAGE_WRITE))
 return -1;
 /* XXX: this code should not depend on lock_user */
@@ -2552,7 +2553,8 @@ static MemTxResult 
address_space_write_continue(AddressSpace *as, hwaddr addr,
 MemTxAttrs attrs,
 const uint8_t *buf,
 int len, hwaddr addr1,
-hwaddr l, MemoryRegion *mr)
+hwaddr l, MemoryRegion *mr,
+bool force)
 {
 uint8_t *ptr;
 uint64_t val;
@@ -2560,7 +2562,14 @@ static MemTxResult 
address_space_write_continue(AddressSpace *as, hwaddr addr,
 bool release_lock = false;
 
 for (;;) {
-if (!memory_access_is_direct(mr, true)) {
+
+if (memory_access_is_direct(mr, true) ||
+(force && memory_region_is_romd(mr))) {
+/* RAM case */
+ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
+memcpy(ptr, buf, l);
+inv

Re: [Qemu-devel] [RFC PATCH] exec: Support non-direct memory writes in cpu_memory_rw_debug

2016-06-30 Thread Andrey Smirnov
On Wed, Jun 29, 2016 at 8:55 AM, Paolo Bonzini  wrote:
> On 28/06/2016 23:44, Andrey Smirnov wrote:
>> Add code to support writing to memory mapped peripherals via
>> cpu_memory_rw_debug(). The code of that function already supports
>> reading from such memory regions, so this commit makes that
>> functionality "symmetric".
>
> It's not entirely symmetric however, as you cannot write to the MMIO
> registers of romd devices.  Is this correct?  So I'll leave to others
> the review of whether the functionality is appropriate.

What I meant by "symmetric" is that with that change address_space_rw
is used in both code-paths: for reading and for writing. As for your
question, I think so, the reason why I kept it that way was to
preserve the old code's behavior (see
cpu_physical_memory_write_rom_internal). However according to the
comments/documentation in memory.h writes to ROM devices in ROMD and
MMIO mode should always be handled via callbacks so there seem to be a
contradiction there. I don't know QEMU codebase well enough to make a
call on who's right, so I tried to keep the old behavior.

> Regarding the code:
>
>> @@ -2621,7 +2625,7 @@ static MemTxResult 
>> address_space_write_continue(AddressSpace *as, hwaddr addr,
>>  }
>>
>>  MemTxResult address_space_write(AddressSpace *as, hwaddr addr, MemTxAttrs 
>> attrs,
>> -const uint8_t *buf, int len)
>> +const uint8_t *buf, int len, bool force)
>
> I would prefer to leave this API as is, and instead add a new API such
> as address_space_write_debug or address_space_program.  It's okay to add
> the "force" argument to address_space_write_continue.

Having thought about that, I agree. Will update in v2.

Andrey



Re: [Qemu-devel] [RFC PATCH] exec: Support non-direct memory writes in cpu_memory_rw_debug

2016-06-30 Thread Andrey Smirnov
On Thu, Jun 30, 2016 at 7:06 AM, Peter Maydell  wrote:
> On 28 June 2016 at 22:44, Andrey Smirnov  wrote:
>> Add code to support writing to memory mapped peripherals via
>> cpu_memory_rw_debug(). The code of that function already supports
>> reading from such memory regions, so this commit makes that
>> functionality "symmetric".
>>
>> One use-case for that functionality is setting various registers of a
>> non-running CPU. A concrete example would be starting QEMU emulating
>> Cortex-M with -S, connecting with GDB and modifying the value of Vector
>> Table Offset register.
>>
>> Signed-off-by: Andrey Smirnov 
>
>>  static uint16_t vring_used_idx(VirtQueue *vq)
>> diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
>> index 9f38edf..d5b4966 100644
>> --- a/include/exec/cpu-all.h
>> +++ b/include/exec/cpu-all.h
>> @@ -302,6 +302,6 @@ void dump_opcount_info(FILE *f, fprintf_function 
>> cpu_fprintf);
>>  #endif /* !CONFIG_USER_ONLY */
>>
>>  int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
>> -uint8_t *buf, int len, int is_write);
>> +uint8_t *buf, int len, MemTxType type);
>>
>>  #endif /* CPU_ALL_H */
>> diff --git a/include/exec/memory.h b/include/exec/memory.h
>> index 4ab6800..8fbaf1b 100644
>> --- a/include/exec/memory.h
>> +++ b/include/exec/memory.h
>> @@ -14,6 +14,13 @@
>>  #ifndef MEMORY_H
>>  #define MEMORY_H
>>
>> +typedef enum {
>> +MEMTX_READ,
>> +MEMTX_WRITE,
>> +MEMTX_PROGRAM,
>> +} MemTxType;
>
> We already have an enum for this: MMUAccessType.
> That is currently unhelpfully located in cpu-common.h, but there's a
> patch on list which should get applied soon which moves it to
> include/qom/cpu.h:
>  http://patchwork.ozlabs.org/patch/635235/
>
>
>> +
>>  #ifndef CONFIG_USER_ONLY
>>
>>  #define DIRTY_MEMORY_VGA   0
>> @@ -1240,6 +1247,7 @@ AddressSpace 
>> *address_space_init_shareable(MemoryRegion *root,
>>   */
>>  void address_space_destroy(AddressSpace *as);
>>
>> +
>>  /**
>>   * address_space_rw: read from or write to an address space.
>>   *
>> @@ -1251,11 +1259,11 @@ void address_space_destroy(AddressSpace *as);
>>   * @addr: address within that address space
>>   * @attrs: memory transaction attributes
>>   * @buf: buffer with the data transferred
>> - * @is_write: indicates the transfer direction
>> + * @type: indicates the transfer type
>>   */
>>  MemTxResult address_space_rw(AddressSpace *as, hwaddr addr,
>>   MemTxAttrs attrs, uint8_t *buf,
>> - int len, bool is_write);
>> + int len, MemTxType type);
>>
>>  /**
>>   * address_space_write: write to address space.
>> @@ -1268,10 +1276,11 @@ MemTxResult address_space_rw(AddressSpace *as, 
>> hwaddr addr,
>>   * @addr: address within that address space
>>   * @attrs: memory transaction attributes
>>   * @buf: buffer with the data transferred
>> + * @force: force writing to ROM areas
>>   */
>>  MemTxResult address_space_write(AddressSpace *as, hwaddr addr,
>>  MemTxAttrs attrs,
>> -const uint8_t *buf, int len);
>> +const uint8_t *buf, int len, bool force);
>>
>>  /* address_space_ld*: load from an address space
>>   * address_space_st*: store to an address space
>
> I think this patch would be easier to review if it was
> split up, something like:
>  * a patch which just converts the is_write bool parameter to the
>enum and updates all the callers, with no change in behaviour
>  * a patch which makes use of the ability to pass in something other
>than 0 or 1
>  * a patch which adds and uses address_space_write_debug(),
>or whatever API we go for
>
> The important bit is splitting the mechanical "convert bool
> to enum" part (which touches lots of files but makes no
> behaviour change) from the part which changes behaviour
> and doesn't touch many files.

OK, sounds good, will update in v2.

Andrey



[Qemu-devel] [PATCH 09/17] imx_fec: Use correct length for packet size

2017-09-18 Thread Andrey Smirnov
Use 'frame_size' instead of 'len' when calling qemu_send_packet(),
failing to do so results in malformed packets send in case when that
packed is fragmented into multiple DMA transactions.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 6045ffe673..c45b9648d9 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -532,7 +532,7 @@ static void imx_enet_do_tx(IMXFECState *s, uint32_t index)
 }
 }
 /* Last buffer in frame.  */
-qemu_send_packet(qemu_get_queue(s->nic), frame, len);
+qemu_send_packet(qemu_get_queue(s->nic), frame, frame_size);
 ptr = frame;
 frame_size = 0;
 if (bd.option & ENET_BD_TX_INT) {
-- 
2.13.5




[Qemu-devel] [PATCH 02/17] imx_fec: Do not calculate FEC

2017-09-18 Thread Andrey Smirnov
Save some computation time and avoid calculating CRC's frame

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 88b4b049d7..75822344fc 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1032,9 +1032,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const 
uint8_t *buf,
 IMXENETBufDesc 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;
 
@@ -1048,8 +1046,6 @@ static ssize_t imx_enet_receive(NetClientState *nc, const 
uint8_t *buf,
 
 /* 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 > ENET_MAX_FRAME_SIZE) {
@@ -1090,9 +1086,10 @@ static ssize_t imx_enet_receive(NetClientState *nc, 
const uint8_t *buf,
 dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
 buf += buf_len;
 if (size < 4) {
+const uint8_t zeros[4] = { 0 };
+
 dma_memory_write(&address_space_memory, buf_addr + buf_len,
- crc_ptr, 4 - size);
-crc_ptr += 4 - size;
+ zeros, 4 - size);
 }
 bd.flags &= ~ENET_BD_E;
 if (size == 0) {
-- 
2.13.5




[Qemu-devel] [PATCH 00/17] Initial i.MX7 support

2017-09-18 Thread Andrey Smirnov
Hi everyone,

This patch series contains the work that I've done in order to enable
support for i.MX7 emulation in QEMU. Majority of the set are just odd
fixes and small features implementation that I had to do to already
exisitng code but last 5 commits contain new emulation code.

As the one before last commit in the series states the supported i.MX7
features are:

* up to 2 Cortex A9 cores (SMP works with PSCI)
* A7 MPCORE (identical to A15 MPCORE)
* 7 i.MX UARTs
* 1 CCM device
* 2 Ethernet controllers (FEC)
* 3 SD controllers (USDHC)
* 1 SNVS device
* 1 WDT device

I also have a follow up series that implements bit needes for PCIe
emulation support (DesignWare IP emulation + supporting code) which
I'll be submitting after this series is accepted.

Feedback is welcome!

Thanks,
Andrey Smirnov

Andrey Smirnov (17):
  imx_fec: Do not link to netdev
  imx_fec: Do not calculate FEC
  imx_fec: Refactor imx_eth_enable_rx()
  imx_fec: Change queue flushing heuristics
  imx_fec: Use ENET_FTRL to determine truncation length
  imx_fec: Use MIN instead of explicit ternary operator
  imx_fec: Emulate SHIFT16 in ENETx_RACC
  imx_fec: Add support for multiple Tx DMA rings
  imx_fec: Use correct length for packet size
  sdhci: Add i.MX specific subtype of SDHCI
  sdhci: Implement write method of ACMD12ERRSTS register
  i.MX: Add i.MX7 CCM, PMU and ANALOG device
  i.MX: Add code to emulate i.MX2 watchdog IP block
  i.MX7: Add code to emulate SNVS IP-block
  include/qemu: Add sizes.h from Linux
  i.MX: Add i.MX7 SOC implementation.
  Implement support for i.MX7 Sabre board

 default-configs/arm-softmmu.mak |   1 +
 hw/arm/Makefile.objs|   2 +
 hw/arm/fsl-imx6.c   |   1 +
 hw/arm/fsl-imx7.c   | 327 
 hw/arm/mcimx7d-sabre.c  | 100 
 hw/misc/Makefile.objs   |   3 +
 hw/misc/imx2_wdt.c  | 117 ++
 hw/misc/imx7_ccm.c  | 201 
 hw/misc/imx7_snvs.c |  84 +++
 hw/net/imx_fec.c| 153 ++-
 hw/sd/sdhci-internal.h  |  15 ++
 hw/sd/sdhci.c   | 126 +++-
 include/hw/arm/fsl-imx7.h   | 114 ++
 include/hw/misc/imx2_wdt.h  |  36 +
 include/hw/misc/imx7_ccm.h  |  76 ++
 include/hw/misc/imx7_snvs.h |  35 +
 include/hw/net/imx_fec.h|  26 +++-
 include/hw/sd/sdhci.h   |   8 +
 include/qemu/sizes.h|  47 ++
 19 files changed, 1433 insertions(+), 39 deletions(-)
 create mode 100644 hw/arm/fsl-imx7.c
 create mode 100644 hw/arm/mcimx7d-sabre.c
 create mode 100644 hw/misc/imx2_wdt.c
 create mode 100644 hw/misc/imx7_ccm.c
 create mode 100644 hw/misc/imx7_snvs.c
 create mode 100644 include/hw/arm/fsl-imx7.h
 create mode 100644 include/hw/misc/imx2_wdt.h
 create mode 100644 include/hw/misc/imx7_ccm.h
 create mode 100644 include/hw/misc/imx7_snvs.h
 create mode 100644 include/qemu/sizes.h

-- 
2.13.5




[Qemu-devel] [PATCH 05/17] imx_fec: Use ENET_FTRL to determine truncation length

2017-09-18 Thread Andrey Smirnov
Frame truncation length, TRUNC_FL, is determined by the contents of
ENET_FTRL register, so convert the code to use it instead of a
hardcoded constant.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 767402909d..989c11be5f 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1050,8 +1050,8 @@ static ssize_t imx_enet_receive(NetClientState *nc, const 
uint8_t *buf,
 size += 4;
 
 /* Huge frames are truncted.  */
-if (size > ENET_MAX_FRAME_SIZE) {
-size = ENET_MAX_FRAME_SIZE;
+if (size > s->regs[ENET_FTRL]) {
+size = s->regs[ENET_FTRL];
 flags |= ENET_BD_TR | ENET_BD_LG;
 }
 
-- 
2.13.5




[Qemu-devel] [PATCH 07/17] imx_fec: Emulate SHIFT16 in ENETx_RACC

2017-09-18 Thread Andrey Smirnov
Needed to support latest Linux kernel driver which relies on that
functionality.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 23 +++
 include/hw/net/imx_fec.h |  2 ++
 2 files changed, 25 insertions(+)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 8a77136d38..bd62d7a75f 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1037,6 +1037,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const 
uint8_t *buf,
 uint32_t buf_addr;
 unsigned int buf_len;
 size_t size = len;
+bool shift16 = s->regs[ENET_RACC] & ENET_RACC_SHIFT16;
 
 FEC_PRINTF("len %d\n", (int)size);
 
@@ -1049,6 +1050,10 @@ static ssize_t imx_enet_receive(NetClientState *nc, 
const uint8_t *buf,
 /* 4 bytes for the CRC.  */
 size += 4;
 
+if (shift16) {
+size += 2;
+}
+
 /* Huge frames are truncted.  */
 if (size > s->regs[ENET_FTRL]) {
 size = s->regs[ENET_FTRL];
@@ -1085,6 +1090,24 @@ static ssize_t imx_enet_receive(NetClientState *nc, 
const uint8_t *buf,
 buf_len += size - 4;
 }
 buf_addr = bd.data;
+
+if (shift16) {
+/*
+ * If SHIFT16 bit of ENETx_RACC register is set we need to
+ * align the payload to 4-byte boundary.
+ */
+const uint8_t zeros[2] = { 0 };
+
+dma_memory_write(&address_space_memory, buf_addr,
+ zeros, sizeof(zeros));
+
+buf_addr += sizeof(zeros);
+buf_len  -= sizeof(zeros);
+
+shift16 = false; /* We only do this once per Ethernet
+  * frame */
+}
+
 dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
 buf += buf_len;
 if (size < 4) {
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
index 4bc8f03ec2..20a6aa98b4 100644
--- a/include/hw/net/imx_fec.h
+++ b/include/hw/net/imx_fec.h
@@ -169,6 +169,8 @@
 #define ENET_TWFR_TFWR_LENGTH  (6)
 #define ENET_TWFR_STRFWD   (1 << 8)
 
+#define ENET_RACC_SHIFT16  BIT(7)
+
 /* Buffer Descriptor.  */
 typedef struct {
 uint16_t length;
-- 
2.13.5




[Qemu-devel] [PATCH 10/17] sdhci: Add i.MX specific subtype of SDHCI

2017-09-18 Thread Andrey Smirnov
IP block found on several generations of i.MX family does not use
vanilla SDHCI implementation and it comes with a number of quirks.

Introduce i.MX SDHCI subtype of SDHCI block to add code necessary to
support unmodified Linux guest driver.

Cc: Peter Maydell 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/sd/sdhci-internal.h |  15 ++
 hw/sd/sdhci.c  | 123 -
 include/hw/sd/sdhci.h  |   8 
 3 files changed, 144 insertions(+), 2 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index 161177cf39..7b9ed06c36 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -91,6 +91,8 @@
 #define SDHC_CTRL_ADMA2_32 0x10
 #define SDHC_CTRL_ADMA2_64 0x18
 #define SDHC_DMA_TYPE(x)   ((x) & SDHC_CTRL_DMA_CHECK_MASK)
+#define SDHC_CTRL_4BITBUS  0x02
+#define SDHC_CTRL_8BITBUS  0x20
 
 /* R/W Power Control Register 0x0 */
 #define SDHC_PWRCON0x29
@@ -229,4 +231,17 @@ enum {
 
 extern const VMStateDescription sdhci_vmstate;
 
+
+#define ESDHC_MIX_CTRL 0x48
+#define ESDHC_VENDOR_SPEC  0xc0
+#define ESDHC_DLL_CTRL 0x60
+
+#define ESDHC_TUNING_CTRL  0xcc
+#define ESDHC_TUNE_CTRL_STATUS 0x68
+#define ESDHC_WTMK_LVL 0x44
+
+#define ESDHC_CTRL_4BITBUS (0x1 << 1)
+#define ESDHC_CTRL_8BITBUS (0x2 << 1)
+
+
 #endif
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 6d6a791ee9..73e7910ba9 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -265,7 +265,8 @@ static void sdhci_send_command(SDHCIState *s)
 }
 }
 
-if ((s->norintstsen & SDHC_NISEN_TRSCMP) &&
+if (!(s->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) &&
+(s->norintstsen & SDHC_NISEN_TRSCMP) &&
 (s->cmdreg & SDHC_CMD_RESPONSE) == SDHC_CMD_RSP_WITH_BUSY) {
 s->norintsts |= SDHC_NIS_TRSCMP;
 }
@@ -1191,6 +1192,8 @@ static void sdhci_initfn(SDHCIState *s)
 
 s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 
sdhci_raise_insertion_irq, s);
 s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, 
s);
+
+s->io_ops = &sdhci_mmio_ops;
 }
 
 static void sdhci_uninitfn(SDHCIState *s)
@@ -1347,7 +1350,7 @@ static void sdhci_sysbus_realize(DeviceState *dev, Error 
** errp)
 s->buf_maxsz = sdhci_get_fifolen(s);
 s->fifo_buffer = g_malloc0(s->buf_maxsz);
 sysbus_init_irq(sbd, &s->irq);
-memory_region_init_io(&s->iomem, OBJECT(s), &sdhci_mmio_ops, s, "sdhci",
+memory_region_init_io(&s->iomem, OBJECT(s), s->io_ops, s, "sdhci",
 SDHC_REGISTERS_MAP_SIZE);
 sysbus_init_mmio(sbd, &s->iomem);
 }
@@ -1386,11 +1389,127 @@ static const TypeInfo sdhci_bus_info = {
 .class_init = sdhci_bus_class_init,
 };
 
+static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
+{
+SDHCIState *s = SYSBUS_SDHCI(opaque);
+uint32_t ret;
+uint16_t hostctl;
+
+switch (offset) {
+default:
+return sdhci_read(opaque, offset, size);
+
+case SDHC_HOSTCTL:
+hostctl = SDHC_DMA_TYPE(s->hostctl) << 5;
+
+if (s->hostctl & SDHC_CTRL_8BITBUS)
+hostctl |= ESDHC_CTRL_8BITBUS;
+
+if (s->hostctl & SDHC_CTRL_4BITBUS)
+hostctl |= ESDHC_CTRL_4BITBUS;
+
+ret = hostctl | (s->blkgap << 16) |
+(s->wakcon << 24);
+
+break;
+
+case ESDHC_DLL_CTRL:
+case ESDHC_TUNE_CTRL_STATUS:
+case 0x6c:
+case ESDHC_TUNING_CTRL:
+case ESDHC_VENDOR_SPEC:
+case ESDHC_MIX_CTRL:
+case ESDHC_WTMK_LVL:
+ret = 0;
+break;
+}
+
+return ret;
+}
+
+static void
+usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
+{
+SDHCIState *s = SYSBUS_SDHCI(opaque);
+uint8_t hostctl = 0;
+uint32_t value = (uint32_t)val;
+
+switch (offset) {
+case ESDHC_DLL_CTRL:
+case ESDHC_TUNE_CTRL_STATUS:
+case 0x6c:
+case ESDHC_TUNING_CTRL:
+case ESDHC_WTMK_LVL:
+case ESDHC_VENDOR_SPEC:
+break;
+
+case SDHC_HOSTCTL:
+if (value & ESDHC_CTRL_8BITBUS)
+hostctl |= SDHC_CTRL_8BITBUS;
+
+if (value & ESDHC_CTRL_4BITBUS)
+hostctl |= ESDHC_CTRL_4BITBUS;
+
+hostctl |= SDHC_DMA_TYPE(value >> 5);
+
+value &= ~0xFE;
+value |= hostctl;
+value &= ~0xFF00;
+value |= s->pwrcon;
+
+sdhci_write(opaque, offset, value, size);
+break;
+
+case ESDHC_MIX_CTRL:
+/*
+ * The layout of the register is slightly different, but we
+ * don't care about those bits
+ 

[Qemu-devel] [PATCH 03/17] imx_fec: Refactor imx_eth_enable_rx()

2017-09-18 Thread Andrey Smirnov
Refactor imx_eth_enable_rx() to have more meaningfull variable name
than 'tmp' and to reduce number of logical negations done.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 75822344fc..84085afe09 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -536,19 +536,19 @@ static void imx_eth_do_tx(IMXFECState *s)
 static void imx_eth_enable_rx(IMXFECState *s)
 {
 IMXFECBufDesc bd;
-bool tmp;
+bool rx_ring_full;
 
 imx_fec_read_bd(&bd, s->rx_descriptor);
 
-tmp = ((bd.flags & ENET_BD_E) != 0);
+rx_ring_full = !(bd.flags & ENET_BD_E);
 
-if (!tmp) {
+if (rx_ring_full) {
 FEC_PRINTF("RX buffer full\n");
 } else if (!s->regs[ENET_RDAR]) {
 qemu_flush_queued_packets(qemu_get_queue(s->nic));
 }
 
-s->regs[ENET_RDAR] = tmp ? ENET_RDAR_RDAR : 0;
+s->regs[ENET_RDAR] = rx_ring_full ? 0 : ENET_RDAR_RDAR;
 }
 
 static void imx_eth_reset(DeviceState *d)
-- 
2.13.5




[Qemu-devel] [PATCH 04/17] imx_fec: Change queue flushing heuristics

2017-09-18 Thread Andrey Smirnov
In current implementation, packet queue flushing logic seem to suffer
from a deadlock like scenario if a packet is received by the interface
before before Rx ring is initialized by Guest's driver. Consider the
following sequence of events:

1. A QEMU instance is started against a TAP device on Linux
   host, running Linux guest, e. g., something to the effect
   of:

   qemu-system-arm \
  -net nic,model=imx.fec,netdev=lan0 \
  netdev tap,id=lan0,ifname=tap0,script=no,downscript=no \
  ... rest of the arguments ...

2. Once QEMU starts, but before guest reaches the point where
   FEC deriver is done initializing the HW, Guest, via TAP
   interface, receives a number of multicast MDNS packets from
   Host (not necessarily true for every OS, but it happens at
   least on Fedora 25)

3. Recieving a packet in such a state results in
   imx_eth_can_receive() returning '0', which in turn causes
   tap_send() to disable corresponding event (tap.c:203)

4. Once Guest's driver reaches the point where it is ready to
   recieve packets it prepares Rx ring descriptors and writes
   ENET_RDAR_RDAR to ENET_RDAR register to indicate to HW that
   more descriptors are ready. And at this points emulation
   layer does this:

 s->regs[index] = ENET_RDAR_RDAR;
 imx_eth_enable_rx(s);

   which, combined with:

  if (!s->regs[ENET_RDAR]) {
 qemu_flush_queued_packets(qemu_get_queue(s->nic));
  }

   results in Rx queue never being flushed and corresponding
   I/O event beign disabled.

Change the code to remember the fact that can_receive callback was
called before Rx ring was ready and use it to make a decision if
receive queue needs to be flushed.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 6 --
 include/hw/net/imx_fec.h | 1 +
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 84085afe09..767402909d 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -544,8 +544,9 @@ static void imx_eth_enable_rx(IMXFECState *s)
 
 if (rx_ring_full) {
 FEC_PRINTF("RX buffer full\n");
-} else if (!s->regs[ENET_RDAR]) {
+} else if (s->needs_flush) {
 qemu_flush_queued_packets(qemu_get_queue(s->nic));
+s->needs_flush = false;
 }
 
 s->regs[ENET_RDAR] = rx_ring_full ? 0 : ENET_RDAR_RDAR;
@@ -930,7 +931,8 @@ static int imx_eth_can_receive(NetClientState *nc)
 
 FEC_PRINTF("\n");
 
-return s->regs[ENET_RDAR] ? 1 : 0;
+s->needs_flush = !s->regs[ENET_RDAR];
+return !!s->regs[ENET_RDAR];
 }
 
 static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
index 62ad473b05..4bc8f03ec2 100644
--- a/include/hw/net/imx_fec.h
+++ b/include/hw/net/imx_fec.h
@@ -252,6 +252,7 @@ typedef struct IMXFECState {
 uint32_t phy_int_mask;
 
 bool is_fec;
+bool needs_flush;
 } IMXFECState;
 
 #endif
-- 
2.13.5




[Qemu-devel] [PATCH 11/17] sdhci: Implement write method of ACMD12ERRSTS register

2017-09-18 Thread Andrey Smirnov
Cc: Peter Maydell 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/sd/sdhci.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 73e7910ba9..9249471957 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1139,6 +1139,9 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, 
unsigned size)
 s->admasysaddr = (s->admasysaddr & (0xULL |
 ((uint64_t)mask << 32))) | ((uint64_t)value << 32);
 break;
+case SDHC_ACMD12ERRSTS:
+MASKED_WRITE(s->acmd12errsts, mask, value);
+break;
 case SDHC_FEAER:
 s->acmd12errsts |= value;
 s->errintsts |= (value >> 16) & s->errintstsen;
-- 
2.13.5




[Qemu-devel] [PATCH 17/17] Implement support for i.MX7 Sabre board

2017-09-18 Thread Andrey Smirnov
Cc: Peter Maydell 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/arm/Makefile.objs   |   2 +-
 hw/arm/mcimx7d-sabre.c | 100 +
 2 files changed, 101 insertions(+), 1 deletion(-)
 create mode 100644 hw/arm/mcimx7d-sabre.c

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 33f6051ae3..fc4a963de8 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -19,5 +19,5 @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
 obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
 obj-$(CONFIG_MPS2) += mps2.o
-obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o
+obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
 
diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
new file mode 100644
index 00..34e3933db8
--- /dev/null
+++ b/hw/arm/mcimx7d-sabre.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * MCIMX7D_SABRE Board System emulation.
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This code is licensed under the GPL, version 2 or later.
+ * See the file `COPYING' in the top level directory.
+ *
+ * It (partially) emulates a mcimx7d_sabre board, with a Freescale
+ * i.MX7 SoC
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/fsl-imx7.h"
+#include "hw/boards.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/device_tree.h"
+#include "qemu/error-report.h"
+#include "sysemu/qtest.h"
+#include "net/net.h"
+
+typedef struct {
+FslIMX7State soc;
+MemoryRegion ram;
+} MCIMX7Sabre;
+
+static void mcimx7d_add_psci_node(const struct arm_boot_info *boot_info, void 
*fdt)
+{
+const char comp[] = "arm,psci-0.2\0arm,psci";
+
+qemu_fdt_add_subnode(fdt, "/psci");
+qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
+qemu_fdt_setprop_string(fdt, "/psci", "method", "smc");
+}
+
+static void mcimx7d_sabre_init(MachineState *machine)
+{
+static struct arm_boot_info boot_info;
+MCIMX7Sabre *s = g_new0(MCIMX7Sabre, 1);
+Object *soc;
+int i;
+
+if (machine->ram_size > FSL_IMX7_MMDC_SIZE) {
+error_report("RAM size " RAM_ADDR_FMT " above max supported (%08x)",
+ machine->ram_size, FSL_IMX7_MMDC_SIZE);
+exit(1);
+}
+
+boot_info = (struct arm_boot_info) {
+.loader_start = FSL_IMX7_MMDC_ADDR,
+.board_id = -1,
+.ram_size = machine->ram_size,
+.kernel_filename = machine->kernel_filename,
+.kernel_cmdline = machine->kernel_cmdline,
+.initrd_filename = machine->initrd_filename,
+.nb_cpus = smp_cpus,
+.modify_dtb = mcimx7d_add_psci_node,
+};
+
+object_initialize(&s->soc, sizeof(s->soc), TYPE_FSL_IMX7);
+soc = OBJECT(&s->soc);
+object_property_add_child(OBJECT(machine), "soc", soc, &error_fatal);
+object_property_set_bool(soc, true, "realized", &error_fatal);
+
+memory_region_allocate_system_memory(&s->ram, NULL, "mcimx7d-sabre.ram",
+ machine->ram_size);
+memory_region_add_subregion(get_system_memory(),
+FSL_IMX7_MMDC_ADDR, &s->ram);
+
+for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) {
+BusState *bus;
+DeviceState *carddev;
+DriveInfo *di;
+BlockBackend *blk;
+
+di = drive_get_next(IF_SD);
+blk = di ? blk_by_legacy_dinfo(di) : NULL;
+bus = qdev_get_child_bus(DEVICE(&s->soc.usdhc[i]), "sd-bus");
+carddev = qdev_create(bus, TYPE_SD_CARD);
+qdev_prop_set_drive(carddev, "drive", blk, &error_fatal);
+object_property_set_bool(OBJECT(carddev), true, "realized", 
&error_fatal);
+}
+
+if (!qtest_enabled()) {
+arm_load_kernel(&s->soc.cpu[0], &boot_info);
+}
+}
+
+static void mcimx7d_sabre_machine_init(MachineClass *mc)
+{
+mc->desc = "Freescale i.MX7 DUAL SABRE (Cortex A7)";
+mc->init = mcimx7d_sabre_init;
+mc->max_cpus = FSL_IMX7_NUM_CPUS;
+mc->ignore_memory_transaction_failures = true;
+}
+DEFINE_MACHINE("mcimx7d-sabre", mcimx7d_sabre_machine_init)
-- 
2.13.5




[Qemu-devel] [PATCH 01/17] imx_fec: Do not link to netdev

2017-09-18 Thread Andrey Smirnov
Binding to a particular netdev doesn't seem to belong to this layer
and should probably be done as a part of board or SoC specific code.

Convert all of the users of this IP block to use
qdev_set_nic_properties() instead.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/arm/fsl-imx6.c | 1 +
 hw/net/imx_fec.c  | 2 --
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index 26fd214004..2ed7146c52 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -385,6 +385,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 spi_table[i].irq));
 }
 
+qdev_set_nic_properties(DEVICE(&s->eth), &nd_table[0]);
 object_property_set_bool(OBJECT(&s->eth), true, "realized", &err);
 if (err) {
 error_propagate(errp, err);
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 90e6ee35ba..88b4b049d7 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1171,8 +1171,6 @@ static void imx_eth_realize(DeviceState *dev, Error 
**errp)
 
 qemu_macaddr_default_if_unset(&s->conf.macaddr);
 
-s->conf.peers.ncs[0] = nd_table[0].netdev;
-
 s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
   object_get_typename(OBJECT(dev)),
   DEVICE(dev)->id, s);
-- 
2.13.5




[Qemu-devel] [PATCH 06/17] imx_fec: Use MIN instead of explicit ternary operator

2017-09-18 Thread Andrey Smirnov
Cc: Peter Maydell 
Cc: Jason Wang 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 989c11be5f..8a77136d38 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1074,7 +1074,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const 
uint8_t *buf,
   TYPE_IMX_FEC, __func__);
 break;
 }
-buf_len = (size <= s->regs[ENET_MRBR]) ? size : s->regs[ENET_MRBR];
+buf_len = MIN(size, s->regs[ENET_MRBR]);
 bd.length = buf_len;
 size -= buf_len;
 
-- 
2.13.5




[Qemu-devel] [PATCH 14/17] i.MX7: Add code to emulate SNVS IP-block

2017-09-18 Thread Andrey Smirnov
Add code to emulate SNVS IP-block. Currently only the bits needed to
be able to emulate machine shutdown are implemented.

Cc: Peter Maydell 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/misc/Makefile.objs   |  1 +
 hw/misc/imx7_snvs.c | 84 +
 include/hw/misc/imx7_snvs.h | 35 +++
 3 files changed, 120 insertions(+)
 create mode 100644 hw/misc/imx7_snvs.c
 create mode 100644 include/hw/misc/imx7_snvs.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index c393a93456..16cee88e0f 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -36,6 +36,7 @@ obj-$(CONFIG_IMX) += imx6_ccm.o
 obj-$(CONFIG_IMX) += imx6_src.o
 obj-$(CONFIG_IMX) += imx7_ccm.o
 obj-$(CONFIG_IMX) += imx2_wdt.o
+obj-$(CONFIG_IMX) += imx7_snvs.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/imx7_snvs.c b/hw/misc/imx7_snvs.c
new file mode 100644
index 00..efce0a760f
--- /dev/null
+++ b/hw/misc/imx7_snvs.c
@@ -0,0 +1,84 @@
+/*
+ * IMX7 Secure Non-Volatile Storage
+ *
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * Bare minimum emulation code needed to support being able to shut
+ * down linux guest gracefully.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/sizes.h"
+#include "hw/misc/imx7_snvs.h"
+#include "qemu/log.h"
+#include "sysemu/sysemu.h"
+
+static uint64_t imx7_snvs_read(void *opaque, hwaddr offset, unsigned size)
+{
+return 0;
+}
+
+static void imx7_snvs_write(void *opaque, hwaddr offset,
+uint64_t v, unsigned size)
+{
+const uint32_t value = v;
+const uint32_t mask  = SNVS_LPCR_TOP | SNVS_LPCR_DP_EN;
+
+if (offset == SNVS_LPCR && ((value & mask) == mask)) {
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+}
+}
+
+static const struct MemoryRegionOps imx7_snvs_ops = {
+.read = imx7_snvs_read,
+.write = imx7_snvs_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void imx7_snvs_init(Object *obj)
+{
+SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+IMX7SNVSState *s = IMX7_SNVS(obj);
+
+memory_region_init_io(&s->mmio, obj, &imx7_snvs_ops, s,
+  TYPE_IMX7_SNVS, 0x1000);
+
+sysbus_init_mmio(sd, &s->mmio);
+}
+
+static void imx7_snvs_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->desc  = "i.MX7 Secure Non-Volatile Storage Module";
+}
+
+static const TypeInfo imx7_snvs_info = {
+.name  = TYPE_IMX7_SNVS,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(IMX7SNVSState),
+.instance_init = imx7_snvs_init,
+.class_init= imx7_snvs_class_init,
+};
+
+static void imx7_snvs_register_type(void)
+{
+type_register_static(&imx7_snvs_info);
+}
+type_init(imx7_snvs_register_type)
diff --git a/include/hw/misc/imx7_snvs.h b/include/hw/misc/imx7_snvs.h
new file mode 100644
index 00..255f8f26f9
--- /dev/null
+++ b/include/hw/misc/imx7_snvs.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 SNVS block emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * 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 IMX7_SNVS_H
+#define IMX7_SNVS_H
+
+#include "qemu/bitops.h"
+#include "hw/sysbus.h"
+
+
+enum IMX7SNVSRegisters {
+SNVS_LPCR = 0x38,
+SNVS_LPCR_TOP   = BIT(6),
+SNVS_LPCR_DP_EN = BIT(5)
+};
+
+#define TYPE_IMX7_SNVS "imx7.snvs"
+#define IMX7_SNVS(obj) OBJECT_CHECK(IMX7SNVSState, (obj), TYPE_IMX7_SNVS)
+
+typedef struct IMX7SNVSState {
+/*  */
+SysBusDevice parent_obj;
+
+MemoryRegion mmio;
+} IMX7SNVSState;
+
+#endif /* IMX7_SNVS_H */
-- 
2.13.5




[Qemu-devel] [PATCH 08/17] imx_fec: Add support for multiple Tx DMA rings

2017-09-18 Thread Andrey Smirnov
More recent version of the IP block support more than one Tx DMA ring,
so add the code implementing that feature.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 97 +++-
 include/hw/net/imx_fec.h | 23 +++-
 2 files changed, 101 insertions(+), 19 deletions(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index bd62d7a75f..6045ffe673 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -196,6 +196,17 @@ static const char *imx_eth_reg_name(IMXFECState *s, 
uint32_t index)
 }
 }
 
+static const VMStateDescription vmstate_imx_eth_tx_ring = {
+.name = "fec-tx-ring",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32(descriptor, IMXFECTxRing),
+VMSTATE_UINT32(tdsr, IMXFECTxRing),
+VMSTATE_END_OF_LIST()
+},
+};
+
 static const VMStateDescription vmstate_imx_eth = {
 .name = TYPE_IMX_FEC,
 .version_id = 2,
@@ -203,8 +214,10 @@ static const VMStateDescription vmstate_imx_eth = {
 .fields = (VMStateField[]) {
 VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX),
 VMSTATE_UINT32(rx_descriptor, IMXFECState),
-VMSTATE_UINT32(tx_descriptor, IMXFECState),
-
+VMSTATE_STRUCT_ARRAY(tx_ring, IMXFECState,
+ ENET_TX_RING_NUM,
+ 1, vmstate_imx_eth_tx_ring,
+ IMXFECTxRing),
 VMSTATE_UINT32(phy_status, IMXFECState),
 VMSTATE_UINT32(phy_control, IMXFECState),
 VMSTATE_UINT32(phy_advertise, IMXFECState),
@@ -407,7 +420,7 @@ static void imx_fec_do_tx(IMXFECState *s)
 int frame_size = 0, descnt = 0;
 uint8_t frame[ENET_MAX_FRAME_SIZE];
 uint8_t *ptr = frame;
-uint32_t addr = s->tx_descriptor;
+uint32_t addr = s->tx_ring[0].descriptor;
 
 while (descnt++ < IMX_MAX_DESC) {
 IMXFECBufDesc bd;
@@ -448,17 +461,38 @@ static void imx_fec_do_tx(IMXFECState *s)
 }
 }
 
-s->tx_descriptor = addr;
+s->tx_ring[0].descriptor = addr;
 
 imx_eth_update(s);
 }
 
-static void imx_enet_do_tx(IMXFECState *s)
+static void imx_enet_do_tx(IMXFECState *s, uint32_t index)
 {
 int frame_size = 0, descnt = 0;
 uint8_t frame[ENET_MAX_FRAME_SIZE];
 uint8_t *ptr = frame;
-uint32_t addr = s->tx_descriptor;
+IMXFECTxRing *ring;
+uint32_t addr;
+
+switch (index) {
+case ENET_TDAR:
+ring = &s->tx_ring[0];
+break;
+case ENET_TDAR1:
+ring = &s->tx_ring[1];
+break;
+case ENET_TDAR2:
+ring = &s->tx_ring[2];
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: bogus value for index %x\n",
+  __func__, index);
+abort();
+break;
+}
+
+addr = ring->descriptor;
 
 while (descnt++ < IMX_MAX_DESC) {
 IMXENETBufDesc bd;
@@ -502,32 +536,32 @@ static void imx_enet_do_tx(IMXFECState *s)
 ptr = frame;
 frame_size = 0;
 if (bd.option & ENET_BD_TX_INT) {
-s->regs[ENET_EIR] |= ENET_INT_TXF;
+s->regs[ENET_EIR] |= ring->int_txf;
 }
 }
 if (bd.option & ENET_BD_TX_INT) {
-s->regs[ENET_EIR] |= ENET_INT_TXB;
+s->regs[ENET_EIR] |= ring->int_txb;
 }
 bd.flags &= ~ENET_BD_R;
 /* Write back the modified descriptor.  */
 imx_enet_write_bd(&bd, addr);
 /* Advance to the next descriptor.  */
 if ((bd.flags & ENET_BD_W) != 0) {
-addr = s->regs[ENET_TDSR];
+addr = s->regs[ring->tdsr];
 } else {
 addr += sizeof(bd);
 }
 }
 
-s->tx_descriptor = addr;
+ring->descriptor = addr;
 
 imx_eth_update(s);
 }
 
-static void imx_eth_do_tx(IMXFECState *s)
+static void imx_eth_do_tx(IMXFECState *s, uint32_t index)
 {
 if (!s->is_fec && (s->regs[ENET_ECR] & ENET_ECR_EN1588)) {
-imx_enet_do_tx(s);
+imx_enet_do_tx(s, index);
 } else {
 imx_fec_do_tx(s);
 }
@@ -586,7 +620,22 @@ static void imx_eth_reset(DeviceState *d)
 }
 
 s->rx_descriptor = 0;
-s->tx_descriptor = 0;
+
+s->tx_ring[0].tdsr = ENET_TDSR;
+s->tx_ring[1].tdsr = ENET_TDSR1;
+s->tx_ring[2].tdsr = ENET_TDSR2;
+
+s->tx_ring[0].int_txf = ENET_INT_TXF;
+s->tx_ring[1].int_txf = ENET_INT_TXF1;
+s->tx_ring[2].int_txf = ENET_INT_TXF2;
+
+s->tx_ring[0].int_txb = ENET_INT_TXB;
+s->tx_ring[1].int_txb = ENET_INT_TXB1;
+s->tx_ring[2].int_txb = ENET_INT_TXB2;
+
+s->tx_ring[0].descriptor = 0;
+s->tx_ring[1].descriptor = 0;
+s

[Qemu-devel] [PATCH 15/17] include/qemu: Add sizes.h from Linux

2017-09-18 Thread Andrey Smirnov
Add sizes.h from Linux to have a more readable way of specifying
MemoryRegion sizes.

Cc: Peter Maydell 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 include/qemu/sizes.h | 47 +++
 1 file changed, 47 insertions(+)
 create mode 100644 include/qemu/sizes.h

diff --git a/include/qemu/sizes.h b/include/qemu/sizes.h
new file mode 100644
index 00..9aedb9f8f6
--- /dev/null
+++ b/include/qemu/sizes.h
@@ -0,0 +1,47 @@
+/*
+ * Copy of include/linux/sizes.h
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef SIZES_H
+#define SIZES_H
+
+#define SZ_1   0x0001
+#define SZ_2   0x0002
+#define SZ_4   0x0004
+#define SZ_8   0x0008
+#define SZ_16  0x0010
+#define SZ_32  0x0020
+#define SZ_64  0x0040
+#define SZ_128 0x0080
+#define SZ_256 0x0100
+#define SZ_512 0x0200
+
+#define SZ_1K  0x0400
+#define SZ_2K  0x0800
+#define SZ_4K  0x1000
+#define SZ_8K  0x2000
+#define SZ_16K 0x4000
+#define SZ_32K 0x8000
+#define SZ_64K 0x0001
+#define SZ_128K0x0002
+#define SZ_256K0x0004
+#define SZ_512K0x0008
+
+#define SZ_1M  0x0010
+#define SZ_2M  0x0020
+#define SZ_4M  0x0040
+#define SZ_8M  0x0080
+#define SZ_16M 0x0100
+#define SZ_32M 0x0200
+#define SZ_64M 0x0400
+#define SZ_128M0x0800
+#define SZ_256M0x1000
+#define SZ_512M0x2000
+
+#define SZ_1G  0x4000
+#define SZ_2G  0x8000
+
+#endif /* SIZES_H */
-- 
2.13.5




[Qemu-devel] [PATCH 16/17] i.MX: Add i.MX7 SOC implementation.

2017-09-18 Thread Andrey Smirnov
For now we only support the following devices:
* up to 2 Cortex A9 cores (SMP works with PSCI)
* A7 MPCORE (identical to A15 MPCORE)
* 7 i.MX UARTs
* 1 CCM device
* 2 Ethernet controllers (FEC)
* 3 SD controllers (USDHC)
* 1 SNVS device
* 1 WDT device

Cc: Peter Maydell 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 default-configs/arm-softmmu.mak |   1 +
 hw/arm/Makefile.objs|   2 +
 hw/arm/fsl-imx7.c   | 327 
 include/hw/arm/fsl-imx7.h   | 114 ++
 4 files changed, 444 insertions(+)
 create mode 100644 hw/arm/fsl-imx7.c
 create mode 100644 include/hw/arm/fsl-imx7.h

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index bbdd3c1d8b..98396a3ad2 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -118,6 +118,7 @@ CONFIG_ALLWINNER_A10=y
 CONFIG_FSL_IMX6=y
 CONFIG_FSL_IMX31=y
 CONFIG_FSL_IMX25=y
+CONFIG_FSL_IMX7=y
 
 CONFIG_IMX_I2C=y
 
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index a2e56ecaae..33f6051ae3 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -19,3 +19,5 @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
 obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
 obj-$(CONFIG_MPS2) += mps2.o
+obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o
+
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
new file mode 100644
index 00..bd01bb7f59
--- /dev/null
+++ b/hw/arm/fsl-imx7.c
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 SoC definitions
+ *
+ * Author: Andrey Smirnov 
+ *
+ * Based on hw/arm/fsl-imx6.c
+ *
+ * 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; version 2 of the License.
+ *
+ * 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.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/fsl-imx7.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+
+#define NAME_SIZE 20
+
+#define for_each_cpu(i) for (i = 0; i < smp_cpus; i++)
+
+static void fsl_imx7_init(Object *obj)
+{
+BusState *sysbus = sysbus_get_default();
+FslIMX7State *s = FSL_IMX7(obj);
+char name[NAME_SIZE];
+int i;
+
+if (smp_cpus > FSL_IMX7_NUM_CPUS) {
+error_report("%s: Only %d CPUs are supported (%d requested)",
+ TYPE_FSL_IMX7, FSL_IMX7_NUM_CPUS, smp_cpus);
+exit(1);
+}
+
+for_each_cpu(i) {
+object_initialize(&s->cpu[i], sizeof(s->cpu[i]),
+  "cortex-a7-" TYPE_ARM_CPU);
+snprintf(name, NAME_SIZE, "cpu%d", i);
+object_property_add_child(obj, name, OBJECT(&s->cpu[i]),
+  &error_fatal);
+}
+
+/*
+ * A7MPCORE
+ */
+object_initialize(&s->a7mpcore, sizeof(s->a7mpcore), TYPE_A15MPCORE_PRIV);
+qdev_set_parent_bus(DEVICE(&s->a7mpcore), sysbus);
+object_property_add_child(obj, "a7mpcore",
+  OBJECT(&s->a7mpcore), &error_fatal);
+
+/*
+ * CCM
+ */
+object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX7_CCM);
+qdev_set_parent_bus(DEVICE(&s->ccm), sysbus);
+object_property_add_child(obj, "ccm", OBJECT(&s->ccm), &error_fatal);
+
+/*
+ * UART
+ */
+for (i = 0; i < FSL_IMX7_NUM_UARTS; i++) {
+object_initialize(&s->uart[i], sizeof(s->uart[i]), 
TYPE_IMX_SERIAL);
+qdev_set_parent_bus(DEVICE(&s->uart[i]), sysbus);
+snprintf(name, NAME_SIZE, "uart%d", i);
+object_property_add_child(obj, name, OBJECT(&s->uart[i]),
+  &error_fatal);
+}
+
+/*
+ * Ethernet
+ */
+for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) {
+object_initialize(&s->eth[i], sizeof(s->eth[i]), TYPE_IMX_ENET);
+qdev_set_parent_bus(DEVICE(&s->eth[i]), sysbus);
+snprintf(name, NAME_SIZE, "eth%d", i);
+object_property_add_child(obj, name, OBJECT(&s->eth[i]),
+  &error_fatal);
+}
+
+/*
+ * SDHCI
+ */
+for (i = 0; i < FSL_IMX7_NUM_USDHCS; i++) {
+object_initialize(&s->usdhc[i], sizeof(s->usdhc[i]),
+  TYPE_IMX_USDHC);
+qdev_se

[Qemu-devel] [PATCH 13/17] i.MX: Add code to emulate i.MX2 watchdog IP block

2017-09-18 Thread Andrey Smirnov
Add enough code to emulate i.MX2 watchdog IP block so it would be
possible to reboot the machine running Linux Guest.

Cc: Peter Maydell 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/misc/Makefile.objs  |   1 +
 hw/misc/imx2_wdt.c | 117 +
 include/hw/misc/imx2_wdt.h |  36 ++
 3 files changed, 154 insertions(+)
 create mode 100644 hw/misc/imx2_wdt.c
 create mode 100644 include/hw/misc/imx2_wdt.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index ac1be05a03..c393a93456 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -35,6 +35,7 @@ obj-$(CONFIG_IMX) += imx25_ccm.o
 obj-$(CONFIG_IMX) += imx6_ccm.o
 obj-$(CONFIG_IMX) += imx6_src.o
 obj-$(CONFIG_IMX) += imx7_ccm.o
+obj-$(CONFIG_IMX) += imx2_wdt.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/imx2_wdt.c b/hw/misc/imx2_wdt.c
new file mode 100644
index 00..9d97a19511
--- /dev/null
+++ b/hw/misc/imx2_wdt.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX2 Watchdog IP block
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/hw.h"
+#include "exec/memory.h"
+#include "exec/address-spaces.h"
+#include "hw/sysbus.h"
+#include "qemu/log.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/watchdog.h"
+#include "qemu/error-report.h"
+#include "qemu/sizes.h"
+
+#include "hw/misc/imx2_wdt.h"
+
+
+#define IMX2_WDT_WCR_WDA   BIT(5)  /* -> External Reset WDOG_B */
+#define IMX2_WDT_WCR_SRS   BIT(4)  /* -> Software Reset Signal */
+
+static uint64_t imx2_wdt_read(void *opaque, hwaddr addr,
+  unsigned int size)
+{
+IMX2WdtState *s = opaque;
+const size_t index = addr / sizeof(s->reg[0]);
+
+if (index < ARRAY_SIZE(s->reg))
+return s->reg[index];
+else
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
+
+return 0xDEADBEEF;
+}
+
+static void imx2_wdt_write(void *opaque, hwaddr addr,
+   uint64_t val64, unsigned int size)
+{
+uint16_t value  = val64;
+IMX2WdtState *s = opaque;
+const size_t index = addr / sizeof(s->reg[0]);
+
+switch (index) {
+case IMX2_WDT_WCR:
+if (value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))
+watchdog_perform_action();
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
+}
+}
+
+static const MemoryRegionOps imx2_wdt_ops = {
+.read  = imx2_wdt_read,
+.write = imx2_wdt_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.valid = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void imx2_wdt_realize(DeviceState *dev, Error **errp)
+{
+IMX2WdtState *s = IMX2_WDT(dev);
+
+memory_region_init_io(&s->mmio, OBJECT(dev),
+  &imx2_wdt_ops, s,
+  TYPE_IMX2_WDT".mmio", SZ_64K);
+sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
+}
+
+static void imx2_wdt_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->realize = imx2_wdt_realize;
+
+set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+}
+
+static const TypeInfo imx2_wdt_info = {
+.name  = TYPE_IMX2_WDT,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(IMX2WdtState),
+.class_init= imx2_wdt_class_init,
+};
+
+static WatchdogTimerModel model = {
+.wdt_name = "imx2-watchdog",
+.wdt_description = "i.MX2 Watchdog",
+};
+
+static void imx2_wdt_register_type(void)
+{
+watchdog_add_model(&model);
+type_register_static(&imx2_wdt_info);
+}
+type_init(imx2_wdt_register_type)
diff --git a/include/hw/misc/imx2_wdt.h b/include/hw/misc/imx2_wdt.h
new file mode 100644
index 00..3a30ed1ef8
--- /dev/null
+++ b/include/hw/misc/imx2_wdt.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX2 Watchdog IP block
+ *
+ * A

[Qemu-devel] [PATCH 12/17] i.MX: Add i.MX7 CCM, PMU and ANALOG device

2017-09-18 Thread Andrey Smirnov
Cc: Peter Maydell 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/misc/Makefile.objs  |   1 +
 hw/misc/imx7_ccm.c | 201 +
 include/hw/misc/imx7_ccm.h |  76 +
 3 files changed, 278 insertions(+)
 create mode 100644 hw/misc/imx7_ccm.c
 create mode 100644 include/hw/misc/imx7_ccm.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 29fb922cef..ac1be05a03 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -34,6 +34,7 @@ obj-$(CONFIG_IMX) += imx31_ccm.o
 obj-$(CONFIG_IMX) += imx25_ccm.o
 obj-$(CONFIG_IMX) += imx6_ccm.o
 obj-$(CONFIG_IMX) += imx6_src.o
+obj-$(CONFIG_IMX) += imx7_ccm.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/imx7_ccm.c b/hw/misc/imx7_ccm.c
new file mode 100644
index 00..418aafe7cc
--- /dev/null
+++ b/hw/misc/imx7_ccm.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 CCM, PMU and ANALOG IP blocks emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/sizes.h"
+#include "hw/misc/imx7_ccm.h"
+#include "qemu/log.h"
+
+static uint32_t imx7_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
+{
+/*
+ * This function is "consumed" by GPT emulation code, however on
+ * i.MX7 each GPT block can have their own clock root. This means
+ * that this functions needs somehow to know requester's identity
+ * and the way to pass it: be it via additional IMXClk constants
+ * or by adding another argument to this method needs to be
+ * figured out
+ */
+qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Not implemented\n",
+  TYPE_IMX7_CCM, __func__);
+return 0;
+}
+
+static void imx7_ccm_reset(DeviceState *dev)
+{
+IMX7CCMState *s = IMX7_CCM(dev);
+
+s->analog[CCM_ANALOG_PLL_ARM] = 0x2042;
+s->analog[CCM_ANALOG_PLL_DDR] = 0x0060302c;
+s->analog[CCM_ANALOG_PLL_DDR_SS]  = 0x;
+s->analog[CCM_ANALOG_PLL_DDR_NUM] = 0x06aaac4d;
+s->analog[CCM_ANALOG_PLL_DDR_DENOM]   = 0x13ec;
+s->analog[CCM_ANALOG_PLL_480] = 0x2000;
+s->analog[CCM_ANALOG_PLL_480A]= 0x52605a56;
+s->analog[CCM_ANALOG_PLL_480B]= 0x52525216;
+s->analog[CCM_ANALOG_PLL_ENET]= 0x1fc0;
+s->analog[CCM_ANALOG_PLL_AUDIO]   = 0x0001301b;
+s->analog[CCM_ANALOG_PLL_AUDIO_SS]= 0x;
+s->analog[CCM_ANALOG_PLL_AUDIO_NUM]   = 0x05f5e100;
+s->analog[CCM_ANALOG_PLL_AUDIO_DENOM] = 0x2964619c;
+s->analog[CCM_ANALOG_PLL_VIDEO]   = 0x0008201b;
+s->analog[CCM_ANALOG_PLL_VIDEO_SS]= 0x;
+s->analog[CCM_ANALOG_PLL_VIDEO_NUM]   = 0xf699;
+s->analog[CCM_ANALOG_PLL_VIDEO_DENOM] = 0x000f4240;
+s->analog[CCM_ANALOG_PLL_MISC0]   = 0x;
+
+/* all PLLs need to be locked */
+s->analog[CCM_ANALOG_PLL_ARM]   |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_DDR]   |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_480]   |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_480A]  |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_480B]  |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_ENET]  |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_AUDIO] |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_VIDEO] |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_MISC0] |= CCM_ANALOG_PLL_LOCK;
+}
+
+#define CCM_INDEX(offset)  (((offset) & ~(hwaddr)0xF) / sizeof(uint32_t))
+#define CCM_BITOP(offset)  ((offset) & (hwaddr)0xF)
+
+enum {
+CCM_BITOP_NONE = 0x00,
+CCM_BITOP_SET  = 0x04,
+CCM_BITOP_CLR  = 0x08,
+CCM_BITOP_TOG  = 0x0C,
+};
+
+static uint64_t imx7_set_clr_tog_read(void *opaque, hwaddr offset,
+  unsigned size)
+{
+const uint32_t *mmio = opaque;
+
+return (uint64_t)mmio[CCM_INDEX(offset)];
+}
+
+static void imx7_set_clr_tog_write(void *opaque, hwaddr offset,
+   uint64_t value, unsigned size)
+{
+const uint8_t  bitop = CCM_BITOP(offset);
+const uint32_t index = CCM_INDEX(offset);
+uint32_t *mmio = opaque;
+
+switch (bitop) {
+case CCM_BITOP_NONE:
+mmio[index]  = value;
+break;
+case CCM_BITOP_SET:
+mmio[index] |= value;
+break;
+case CCM_BITOP_CLR:
+mmio[index] &= ~value;
+break;
+case CCM_BITOP_TOG:
+mmio[index] ^= value;
+break;
+};
+}
+
+static const struct MemoryReg

Re: [Qemu-devel] [PATCH 04/17] imx_fec: Change queue flushing heuristics

2017-09-25 Thread Andrey Smirnov
On Fri, Sep 22, 2017 at 12:27 AM, Jason Wang  wrote:
>
>
> On 2017年09月19日 03:50, Andrey Smirnov wrote:
>>
>> In current implementation, packet queue flushing logic seem to suffer
>> from a deadlock like scenario if a packet is received by the interface
>> before before Rx ring is initialized by Guest's driver. Consider the
>> following sequence of events:
>>
>> 1. A QEMU instance is started against a TAP device on Linux
>>host, running Linux guest, e. g., something to the effect
>>of:
>>
>>qemu-system-arm \
>>   -net nic,model=imx.fec,netdev=lan0 \
>>   netdev tap,id=lan0,ifname=tap0,script=no,downscript=no \
>>   ... rest of the arguments ...
>>
>> 2. Once QEMU starts, but before guest reaches the point where
>>FEC deriver is done initializing the HW, Guest, via TAP
>>interface, receives a number of multicast MDNS packets from
>>Host (not necessarily true for every OS, but it happens at
>>least on Fedora 25)
>>
>> 3. Recieving a packet in such a state results in
>>imx_eth_can_receive() returning '0', which in turn causes
>>tap_send() to disable corresponding event (tap.c:203)
>>
>> 4. Once Guest's driver reaches the point where it is ready to
>>recieve packets it prepares Rx ring descriptors and writes
>>ENET_RDAR_RDAR to ENET_RDAR register to indicate to HW that
>>more descriptors are ready. And at this points emulation
>>layer does this:
>>
>>  s->regs[index] = ENET_RDAR_RDAR;
>>   imx_eth_enable_rx(s);
>>
>>which, combined with:
>>
>>   if (!s->regs[ENET_RDAR]) {
>>  qemu_flush_queued_packets(qemu_get_queue(s->nic));
>>   }
>
>
> Not familiar with FEC, but if you are tracking 0->1 transition, why not
> simply introduce a parameter of imx_eth_enable_rx() to force the flushing?
>

Not sure I fully understand you, are you proposing I get rid of
"needs_flush" parameter in the device state, converting it to be a
parameter to imx_eth_enable_rx(), and then force flushing every time
imx_eth_enable_rx() is called in imx_eth_write()?

That should work, but it'll end up making the emulator code to flush
corresponding NIC queue every time the driver is done processing RX
ring. If that is not a big problem I am more than happy to make that
change.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH 08/17] imx_fec: Add support for multiple Tx DMA rings

2017-09-25 Thread Andrey Smirnov
On Fri, Sep 22, 2017 at 12:33 AM, Jason Wang  wrote:
>
>
> On 2017年09月19日 03:50, Andrey Smirnov wrote:
>>
>> More recent version of the IP block support more than one Tx DMA ring,
>> so add the code implementing that feature.
>>
>> Cc: Peter Maydell
>> Cc: Jason Wang
>> Cc:qemu-devel@nongnu.org
>> Cc:qemu-...@nongnu.org
>> Cc:yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov
>> ---
>>   hw/net/imx_fec.c | 97
>> +++-
>>   include/hw/net/imx_fec.h | 23 +++-
>>   2 files changed, 101 insertions(+), 19 deletions(-)
>
>
> Is there a register for driver to know about the version? (Looks like I
> didn't find it).

I haven't seen anything of the sort in the datasheet and, since Linux
driver relies on DT for that information, I am inclined to think
there's none.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH 02/17] imx_fec: Do not calculate FEC

2017-10-09 Thread Andrey Smirnov
On Fri, Oct 6, 2017 at 6:48 AM, Peter Maydell  wrote:
> On 18 September 2017 at 20:50, Andrey Smirnov  
> wrote:
>> Save some computation time and avoid calculating CRC's frame
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  hw/net/imx_fec.c | 9 +++--
>>  1 file changed, 3 insertions(+), 6 deletions(-)
>>
>> diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
>> index 88b4b049d7..75822344fc 100644
>> --- a/hw/net/imx_fec.c
>> +++ b/hw/net/imx_fec.c
>> @@ -1032,9 +1032,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, 
>> const uint8_t *buf,
>>  IMXENETBufDesc 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;
>>
>> @@ -1048,8 +1046,6 @@ static ssize_t imx_enet_receive(NetClientState *nc, 
>> const uint8_t *buf,
>>
>>  /* 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 > ENET_MAX_FRAME_SIZE) {
>> @@ -1090,9 +1086,10 @@ static ssize_t imx_enet_receive(NetClientState *nc, 
>> const uint8_t *buf,
>>  dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
>>  buf += buf_len;
>>  if (size < 4) {
>> +const uint8_t zeros[4] = { 0 };
>> +
>>  dma_memory_write(&address_space_memory, buf_addr + buf_len,
>> - crc_ptr, 4 - size);
>> -crc_ptr += 4 - size;
>> + zeros, 4 - size);
>>  }
>>  bd.flags &= ~ENET_BD_E;
>>  if (size == 0) {
>
> This looks a bit odd. Doesn't the hardware calculate the CRC here?
>

It does, it just seemed to me that since the hardware also has a "CRC
error" bit in its status register, there would be few if any users of
the actual calculated CRC value. Given how eTSEC emulation layer gets
away without calculating CRC I thought that it might be possible to
have this optimization here as well.

I can drop this patch if this seems risky.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH 04/17] imx_fec: Change queue flushing heuristics

2017-10-09 Thread Andrey Smirnov
On Fri, Oct 6, 2017 at 6:56 AM, Peter Maydell  wrote:
> On 18 September 2017 at 20:50, Andrey Smirnov  
> wrote:
>> In current implementation, packet queue flushing logic seem to suffer
>> from a deadlock like scenario if a packet is received by the interface
>> before before Rx ring is initialized by Guest's driver. Consider the
>> following sequence of events:
>>
>> 1. A QEMU instance is started against a TAP device on Linux
>>host, running Linux guest, e. g., something to the effect
>>of:
>>
>>qemu-system-arm \
>>   -net nic,model=imx.fec,netdev=lan0 \
>>   netdev tap,id=lan0,ifname=tap0,script=no,downscript=no \
>>   ... rest of the arguments ...
>>
>> 2. Once QEMU starts, but before guest reaches the point where
>>FEC deriver is done initializing the HW, Guest, via TAP
>>interface, receives a number of multicast MDNS packets from
>>Host (not necessarily true for every OS, but it happens at
>>least on Fedora 25)
>>
>> 3. Recieving a packet in such a state results in
>>imx_eth_can_receive() returning '0', which in turn causes
>>tap_send() to disable corresponding event (tap.c:203)
>>
>> 4. Once Guest's driver reaches the point where it is ready to
>>recieve packets it prepares Rx ring descriptors and writes
>>ENET_RDAR_RDAR to ENET_RDAR register to indicate to HW that
>>more descriptors are ready. And at this points emulation
>>layer does this:
>>
>>  s->regs[index] = ENET_RDAR_RDAR;
>>  imx_eth_enable_rx(s);
>>
>>which, combined with:
>>
>>   if (!s->regs[ENET_RDAR]) {
>>  qemu_flush_queued_packets(qemu_get_queue(s->nic));
>>   }
>>
>>results in Rx queue never being flushed and corresponding
>>I/O event beign disabled.
>>
>> Change the code to remember the fact that can_receive callback was
>> called before Rx ring was ready and use it to make a decision if
>> receive queue needs to be flushed.
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  hw/net/imx_fec.c | 6 --
>>  include/hw/net/imx_fec.h | 1 +
>>  2 files changed, 5 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
>> index 84085afe09..767402909d 100644
>> --- a/hw/net/imx_fec.c
>> +++ b/hw/net/imx_fec.c
>> @@ -544,8 +544,9 @@ static void imx_eth_enable_rx(IMXFECState *s)
>>
>>  if (rx_ring_full) {
>>  FEC_PRINTF("RX buffer full\n");
>> -} else if (!s->regs[ENET_RDAR]) {
>> +} else if (s->needs_flush) {
>>  qemu_flush_queued_packets(qemu_get_queue(s->nic));
>> +s->needs_flush = false;
>>  }
>>
>>  s->regs[ENET_RDAR] = rx_ring_full ? 0 : ENET_RDAR_RDAR;
>> @@ -930,7 +931,8 @@ static int imx_eth_can_receive(NetClientState *nc)
>>
>>  FEC_PRINTF("\n");
>>
>> -return s->regs[ENET_RDAR] ? 1 : 0;
>> +s->needs_flush = !s->regs[ENET_RDAR];
>> +return !!s->regs[ENET_RDAR];
>>  }
>>
>>  static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
>> diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
>> index 62ad473b05..4bc8f03ec2 100644
>> --- a/include/hw/net/imx_fec.h
>> +++ b/include/hw/net/imx_fec.h
>> @@ -252,6 +252,7 @@ typedef struct IMXFECState {
>>  uint32_t phy_int_mask;
>>
>>  bool is_fec;
>> +bool needs_flush;
>>  } IMXFECState;
>
> This looks odd -- I don't think you should need extra
> state here. Conceptually what you want is:
>
>  * in the can_receive callback, test some function of
> various bits of device state to decide whether you can
> take data
>  * in the rest of the device, whenever the device state
> changes such that you were previously not able to take
> data but now you can, call qemu_flush_queued_packets().
>
> You shouldn't need any extra state to do this, you just
> need to fix the bug where you have a code path that
> flips ENET_RDAR from 0 to 1 without calling flush
> (you might for instance have a helper function for
> "set ENET_RDAR" that encapsulates setting the state
> and arranging that flush is called).
>

I don't know if you've seen my response to Jason Wang, but I think he
was proposing something similar, and, as I said, that should work fine
and the only reason I didn't do it that way was to avoid doing a flush
every time that host driver drains full RX-ring and gives it back to
the IP block.

I'll give this a try in v2.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH 05/17] imx_fec: Use ENET_FTRL to determine truncation length

2017-10-09 Thread Andrey Smirnov
On Fri, Oct 6, 2017 at 7:00 AM, Peter Maydell  wrote:
> On 30 September 2017 at 01:17, Philippe Mathieu-Daudé  wrote:
>> Hi Andrey,
>>
>> On 09/18/2017 04:50 PM, Andrey Smirnov wrote:
>>>
>>> Frame truncation length, TRUNC_FL, is determined by the contents of
>>> ENET_FTRL register, so convert the code to use it instead of a
>>> hardcoded constant.
>>>
>>> Cc: Peter Maydell 
>>> Cc: Jason Wang 
>>> Cc: qemu-devel@nongnu.org
>>> Cc: qemu-...@nongnu.org
>>> Cc: yurov...@gmail.com
>>> Signed-off-by: Andrey Smirnov 
>>> ---
>>>   hw/net/imx_fec.c | 4 ++--
>>>   1 file changed, 2 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
>>> index 767402909d..989c11be5f 100644
>>> --- a/hw/net/imx_fec.c
>>> +++ b/hw/net/imx_fec.c
>>> @@ -1050,8 +1050,8 @@ static ssize_t imx_enet_receive(NetClientState *nc,
>>> const uint8_t *buf,
>>>   size += 4;
>>> /* Huge frames are truncted.  */
>>> -if (size > ENET_MAX_FRAME_SIZE) {
>>> -size = ENET_MAX_FRAME_SIZE;
>>> +if (size > s->regs[ENET_FTRL]) {
>>> +size = s->regs[ENET_FTRL]; >   flags |= ENET_BD_TR |
>>> ENET_BD_LG;
>>>   }
>>
>>
>> for this to be ok you need to update imx_enet_write(), such:
>>
>>  case ENET_FTRL:
>> -s->regs[index] = value & 0x3fff;
>> +value &= 0x3fff;
>> +if (value > ENET_MAX_FRAME_SIZE) {
>> +warn_report("%s: guest requested bigger "
>> +"frame size than QEMU supports "
>> +"(%u > %u)", value,
>> +ENET_MAX_FRAME_SIZE);
>> +value = ENET_MAX_FRAME_SIZE;
>> +}
>> +s->regs[index] = value;
>>  break;
>
> Yes, and also an incoming-migration post_load callback that
> fails migration if the value is too large.
>
> It might be simpler to truncate to the smaller of the ENET_FTRL
> register value and ENET_MAX_FRAME_SIZE.
>
> (PS: what is the hardware behaviour if ENET_FTRL is set to
> a larger value than ENET_MAX_FRAME_SIZE ?)
>

I haven't tested it in practice, but I assume that hardware should be
capable of receiving packets of up to ENET_RCR[MAX_FL] bytes big (both
RCR[MAX_FL] and FTRL are 14-bits), since that would allow supporting
networks with jumbo frames.

What if ENET_MAX_FRAME_SIZE is increased to 16K instead? Would that
make all of that additional error checking code unnecessary?

Thanks,
Andrey Smirnov

P.S: And sure, I'll fix the typo in v2.



Re: [Qemu-devel] [PATCH 07/17] imx_fec: Emulate SHIFT16 in ENETx_RACC

2017-10-09 Thread Andrey Smirnov
On Fri, Oct 6, 2017 at 7:02 AM, Peter Maydell  wrote:
> On 18 September 2017 at 20:50, Andrey Smirnov  
> wrote:
>> Needed to support latest Linux kernel driver which relies on that
>> functionality.
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  hw/net/imx_fec.c | 23 +++
>>  include/hw/net/imx_fec.h |  2 ++
>>  2 files changed, 25 insertions(+)
>>
>> diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
>> index 8a77136d38..bd62d7a75f 100644
>> --- a/hw/net/imx_fec.c
>> +++ b/hw/net/imx_fec.c
>> @@ -1037,6 +1037,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, 
>> const uint8_t *buf,
>>  uint32_t buf_addr;
>>  unsigned int buf_len;
>>  size_t size = len;
>> +bool shift16 = s->regs[ENET_RACC] & ENET_RACC_SHIFT16;
>>
>>  FEC_PRINTF("len %d\n", (int)size);
>>
>> @@ -1049,6 +1050,10 @@ static ssize_t imx_enet_receive(NetClientState *nc, 
>> const uint8_t *buf,
>>  /* 4 bytes for the CRC.  */
>>  size += 4;
>>
>> +if (shift16) {
>> +size += 2;
>> +}
>> +
>>  /* Huge frames are truncted.  */
>>  if (size > s->regs[ENET_FTRL]) {
>>  size = s->regs[ENET_FTRL];
>> @@ -1085,6 +1090,24 @@ static ssize_t imx_enet_receive(NetClientState *nc, 
>> const uint8_t *buf,
>>  buf_len += size - 4;
>>  }
>>  buf_addr = bd.data;
>> +
>> +if (shift16) {
>> +/*
>> + * If SHIFT16 bit of ENETx_RACC register is set we need to
>> + * align the payload to 4-byte boundary.
>> + */
>> +const uint8_t zeros[2] = { 0 };
>> +
>> +dma_memory_write(&address_space_memory, buf_addr,
>> + zeros, sizeof(zeros));
>> +
>> +buf_addr += sizeof(zeros);
>> +    buf_len  -= sizeof(zeros);
>> +
>> +shift16 = false; /* We only do this once per Ethernet
>> +  * frame */
>> +}
>> +
>
> Can you avoid having an end-of-source-line comment that wraps
> to multiple lines, please? (put it on a line of its own, or
> edit down to fit.) Otherwise
>

Sure, will fix in v2.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH 08/17] imx_fec: Add support for multiple Tx DMA rings

2017-10-09 Thread Andrey Smirnov
On Fri, Oct 6, 2017 at 7:10 AM, Peter Maydell  wrote:
> On 18 September 2017 at 20:50, Andrey Smirnov  
> wrote:
>> More recent version of the IP block support more than one Tx DMA ring,
>> so add the code implementing that feature.
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>
> I'm surprised this doesn't mean "we have a property on the device
> to indicate what IP version it is, which the boards set". Or are
> all our current boards mismodelling their ethernet devices with the
> wrong number of TX rings ?
>

As far as I know the only already emulated SoC that this affects is
i.MX6, and, no, it doesn't mismodel its Ethernet device since it has
version of the IP block with only one Tx ring. I didn't add any notion
of versioning because it didn't seem necessary, since 3-ring IP block
should be backwards compatible with 1-ring version and host drivers
written for the latter will end up using only ring #1 of the 3-ring
block.

>> ---
>>  hw/net/imx_fec.c | 97 
>> +++-
>>  include/hw/net/imx_fec.h | 23 +++-
>>  2 files changed, 101 insertions(+), 19 deletions(-)
>>
>> diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
>> index bd62d7a75f..6045ffe673 100644
>> --- a/hw/net/imx_fec.c
>> +++ b/hw/net/imx_fec.c
>> @@ -196,6 +196,17 @@ static const char *imx_eth_reg_name(IMXFECState *s, 
>> uint32_t index)
>>  }
>>  }
>>
>> +static const VMStateDescription vmstate_imx_eth_tx_ring = {
>> +.name = "fec-tx-ring",
>> +.version_id = 1,
>> +.minimum_version_id = 1,
>> +.fields = (VMStateField[]) {
>> +VMSTATE_UINT32(descriptor, IMXFECTxRing),
>> +VMSTATE_UINT32(tdsr, IMXFECTxRing),
>> +VMSTATE_END_OF_LIST()
>> +},
>> +};
>> +
>>  static const VMStateDescription vmstate_imx_eth = {
>>  .name = TYPE_IMX_FEC,
>>  .version_id = 2,
>> @@ -203,8 +214,10 @@ static const VMStateDescription vmstate_imx_eth = {
>>  .fields = (VMStateField[]) {
>>  VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX),
>>  VMSTATE_UINT32(rx_descriptor, IMXFECState),
>> -VMSTATE_UINT32(tx_descriptor, IMXFECState),
>> -
>> +VMSTATE_STRUCT_ARRAY(tx_ring, IMXFECState,
>> + ENET_TX_RING_NUM,
>> + 1, vmstate_imx_eth_tx_ring,
>> + IMXFECTxRing),
>>  VMSTATE_UINT32(phy_status, IMXFECState),
>>  VMSTATE_UINT32(phy_control, IMXFECState),
>>  VMSTATE_UINT32(phy_advertise, IMXFECState),
>
> This breaks migration compatibility, so you need to figure out
> how you want to handle that. The simple solution is to increment
> the version_id and minimum_version_id fields in vmstate_imx_eth;
> that will mean migration from an old QEMU to a new one doesn't
> work but it fails in a clean way. The complex way is to put the
> new state into a migration subsection with a .needed function
> to determine whether to use it or not. For imx I think we can
> get away with the simple solution.
>

OK, will do in v2.

>> @@ -407,7 +420,7 @@ static void imx_fec_do_tx(IMXFECState *s)
>>  int frame_size = 0, descnt = 0;
>>  uint8_t frame[ENET_MAX_FRAME_SIZE];
>>  uint8_t *ptr = frame;
>> -uint32_t addr = s->tx_descriptor;
>> +uint32_t addr = s->tx_ring[0].descriptor;
>>
>>  while (descnt++ < IMX_MAX_DESC) {
>>  IMXFECBufDesc bd;
>> @@ -448,17 +461,38 @@ static void imx_fec_do_tx(IMXFECState *s)
>>  }
>>  }
>>
>> -s->tx_descriptor = addr;
>> +s->tx_ring[0].descriptor = addr;
>>
>>  imx_eth_update(s);
>>  }
>>
>> -static void imx_enet_do_tx(IMXFECState *s)
>> +static void imx_enet_do_tx(IMXFECState *s, uint32_t index)
>>  {
>>  int frame_size = 0, descnt = 0;
>>  uint8_t frame[ENET_MAX_FRAME_SIZE];
>>  uint8_t *ptr = frame;
>> -uint32_t addr = s->tx_descriptor;
>> +IMXFECTxRing *ring;
>> +uint32_t addr;
>> +
>> +switch (index) {
>> +case ENET_TDAR:
>> +ring = &s->tx_ring[0];
>> +break;
>> +case ENET_TDAR1:
>> +ring = &s->tx_ring[1];
>> +break;
>> +case ENET_TDAR2:
>> +ring = &s->tx_ring[2];
>> +break;
>> 

Re: [Qemu-devel] [PATCH 15/17] include/qemu: Add sizes.h from Linux

2017-10-09 Thread Andrey Smirnov
On Fri, Oct 6, 2017 at 7:13 AM, Peter Maydell  wrote:
> On 18 September 2017 at 20:50, Andrey Smirnov  
> wrote:
>> Add sizes.h from Linux to have a more readable way of specifying
>> MemoryRegion sizes.
>>
>> Cc: Peter Maydell 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  include/qemu/sizes.h | 47 +++
>>  1 file changed, 47 insertions(+)
>>  create mode 100644 include/qemu/sizes.h
>>
>> diff --git a/include/qemu/sizes.h b/include/qemu/sizes.h
>> new file mode 100644
>> index 00..9aedb9f8f6
>> --- /dev/null
>> +++ b/include/qemu/sizes.h
>> @@ -0,0 +1,47 @@
>> +/*
>> + * Copy of include/linux/sizes.h
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + */
>
> Not really convinced of the utility, and it's gpl-2-only, so no thanks.
>

OK, will drop in v2.

Thanks,
Andrey Smironv



Re: [Qemu-devel] [PATCH 13/17] i.MX: Add code to emulate i.MX2 watchdog IP block

2017-10-09 Thread Andrey Smirnov
On Fri, Oct 6, 2017 at 7:22 AM, Peter Maydell  wrote:
> On 18 September 2017 at 20:50, Andrey Smirnov  
> wrote:
>> Add enough code to emulate i.MX2 watchdog IP block so it would be
>> possible to reboot the machine running Linux Guest.
>>
>> Cc: Peter Maydell 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  hw/misc/Makefile.objs  |   1 +
>>  hw/misc/imx2_wdt.c | 117 
>> +
>>  include/hw/misc/imx2_wdt.h |  36 ++
>>  3 files changed, 154 insertions(+)
>>  create mode 100644 hw/misc/imx2_wdt.c
>>  create mode 100644 include/hw/misc/imx2_wdt.h
>>
>> diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
>> index ac1be05a03..c393a93456 100644
>> --- a/hw/misc/Makefile.objs
>> +++ b/hw/misc/Makefile.objs
>> @@ -35,6 +35,7 @@ obj-$(CONFIG_IMX) += imx25_ccm.o
>>  obj-$(CONFIG_IMX) += imx6_ccm.o
>>  obj-$(CONFIG_IMX) += imx6_src.o
>>  obj-$(CONFIG_IMX) += imx7_ccm.o
>> +obj-$(CONFIG_IMX) += imx2_wdt.o
>>  obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
>>  obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
>>  obj-$(CONFIG_MAINSTONE) += mst_fpga.o
>> diff --git a/hw/misc/imx2_wdt.c b/hw/misc/imx2_wdt.c
>> new file mode 100644
>> index 00..9d97a19511
>> --- /dev/null
>> +++ b/hw/misc/imx2_wdt.c
>> @@ -0,0 +1,117 @@
>> +/*
>> + * Copyright (c) 2017, Impinj, Inc.
>> + *
>> + * i.MX2 Watchdog IP block
>> + *
>> + * Author: Andrey Smirnov 
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
>> + * See the COPYING file in the top-level directory.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "qapi/error.h"
>> +#include "qemu-common.h"
>> +#include "hw/hw.h"
>> +#include "exec/memory.h"
>> +#include "exec/address-spaces.h"
>> +#include "hw/sysbus.h"
>> +#include "qemu/log.h"
>> +#include "qemu/timer.h"
>> +#include "sysemu/sysemu.h"
>> +#include "sysemu/watchdog.h"
>> +#include "qemu/error-report.h"
>> +#include "qemu/sizes.h"
>
> That's an awful lot of includes for a very simple device. Are
> you sure they're all needed?

No, I am not sure. I'll double-check.

>
>> +
>> +#include "hw/misc/imx2_wdt.h"
>> +
>> +
>> +#define IMX2_WDT_WCR_WDA   BIT(5)  /* -> External Reset WDOG_B 
>> */
>> +#define IMX2_WDT_WCR_SRS   BIT(4)  /* -> Software Reset Signal 
>> */
>> +
>> +static uint64_t imx2_wdt_read(void *opaque, hwaddr addr,
>> +  unsigned int size)
>> +{
>> +IMX2WdtState *s = opaque;
>> +const size_t index = addr / sizeof(s->reg[0]);
>> +
>> +if (index < ARRAY_SIZE(s->reg))
>> +return s->reg[index];
>> +else
>> +qemu_log_mask(LOG_GUEST_ERROR,
>> +  "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
>> +
>> +return 0xDEADBEEF;
>> +}
>> +
>> +static void imx2_wdt_write(void *opaque, hwaddr addr,
>> +   uint64_t val64, unsigned int size)
>> +{
>> +uint16_t value  = val64;
>> +IMX2WdtState *s = opaque;
>> +const size_t index = addr / sizeof(s->reg[0]);
>> +
>> +switch (index) {
>> +case IMX2_WDT_WCR:
>> +if (value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))
>> +watchdog_perform_action();
>
> Missing "break"?
>

Oops, good catch! Will fix in v2.

> Also checkpatch should tell you you need more braces.
>

Yeah, I definitely forgot to run this through checkpatch, sorry.

>> +default:
>> +qemu_log_mask(LOG_GUEST_ERROR,
>> +  "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
>> +}
>> +}
>> +
>> +static const MemoryRegionOps imx2_wdt_ops = {
>> +.read  = imx2_wdt_read,
>> +.write = imx2_wdt_write,
>> +.endianness = DEVICE_NATIVE_ENDIAN,
>> +.valid = {
>> +/*
>> + * Our device would not work correctly if the guest was doing
>> + * unaligned access. This might not be a limitation on the real
>> + * device but in practice there is no reason for a guest to access
>> + * this dev

Re: [Qemu-devel] [PATCH 16/17] i.MX: Add i.MX7 SOC implementation.

2017-10-09 Thread Andrey Smirnov
On Fri, Oct 6, 2017 at 7:38 AM, Peter Maydell  wrote:
> On 18 September 2017 at 20:50, Andrey Smirnov  
> wrote:
>> For now we only support the following devices:
>> * up to 2 Cortex A9 cores (SMP works with PSCI)
>> * A7 MPCORE (identical to A15 MPCORE)
>> * 7 i.MX UARTs
>> * 1 CCM device
>> * 2 Ethernet controllers (FEC)
>> * 3 SD controllers (USDHC)
>> * 1 SNVS device
>> * 1 WDT device
>>
>> Cc: Peter Maydell 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  default-configs/arm-softmmu.mak |   1 +
>>  hw/arm/Makefile.objs|   2 +
>>  hw/arm/fsl-imx7.c   | 327 
>> 
>>  include/hw/arm/fsl-imx7.h   | 114 ++
>>  4 files changed, 444 insertions(+)
>>  create mode 100644 hw/arm/fsl-imx7.c
>>  create mode 100644 include/hw/arm/fsl-imx7.h
>>
>> diff --git a/default-configs/arm-softmmu.mak 
>> b/default-configs/arm-softmmu.mak
>> index bbdd3c1d8b..98396a3ad2 100644
>> --- a/default-configs/arm-softmmu.mak
>> +++ b/default-configs/arm-softmmu.mak
>> @@ -118,6 +118,7 @@ CONFIG_ALLWINNER_A10=y
>>  CONFIG_FSL_IMX6=y
>>  CONFIG_FSL_IMX31=y
>>  CONFIG_FSL_IMX25=y
>> +CONFIG_FSL_IMX7=y
>>
>>  CONFIG_IMX_I2C=y
>>
>> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
>> index a2e56ecaae..33f6051ae3 100644
>> --- a/hw/arm/Makefile.objs
>> +++ b/hw/arm/Makefile.objs
>> @@ -19,3 +19,5 @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
>>  obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
>>  obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
>>  obj-$(CONFIG_MPS2) += mps2.o
>> +obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o
>> +
>> diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
>> new file mode 100644
>> index 00..bd01bb7f59
>> --- /dev/null
>> +++ b/hw/arm/fsl-imx7.c
>> @@ -0,0 +1,327 @@
>> +/*
>> + * Copyright (c) 2017, Impinj, Inc.
>> + *
>> + * i.MX7 SoC definitions
>> + *
>> + * Author: Andrey Smirnov 
>> + *
>> + * Based on hw/arm/fsl-imx6.c
>> + *
>> + * 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; version 2 of the License.
>
> We pretty strongly prefer GPL-2-or-later for new code, not 2-only.
>

OK, will change in v2.

>> + *
>> + * 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.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "qapi/error.h"
>> +#include "qemu-common.h"
>> +#include "hw/arm/fsl-imx7.h"
>> +#include "sysemu/sysemu.h"
>> +#include "qemu/error-report.h"
>> +
>> +#define NAME_SIZE 20
>> +
>> +#define for_each_cpu(i) for (i = 0; i < smp_cpus; i++)
>
> Just open-code this, please.

Sure, will do in v2.

>
>> +
>> +static void fsl_imx7_init(Object *obj)
>> +{
>> +BusState *sysbus = sysbus_get_default();
>> +FslIMX7State *s = FSL_IMX7(obj);
>> +char name[NAME_SIZE];
>> +int i;
>> +
>> +if (smp_cpus > FSL_IMX7_NUM_CPUS) {
>> +error_report("%s: Only %d CPUs are supported (%d requested)",
>> + TYPE_FSL_IMX7, FSL_IMX7_NUM_CPUS, smp_cpus);
>> +exit(1);
>> +}
>> +
>> +for_each_cpu(i) {
>> +object_initialize(&s->cpu[i], sizeof(s->cpu[i]),
>> +  "cortex-a7-" TYPE_ARM_CPU);
>> +snprintf(name, NAME_SIZE, "cpu%d", i);
>> +object_property_add_child(obj, name, OBJECT(&s->cpu[i]),
>> +  &error_fatal);
>> +}
>> +
>> +/*
>> + * A7MPCORE
>> + */
>> +object_initialize(&s->a7mpcore, sizeof(s->a7mpcore), 
>> TYPE_A15MPCORE_PRIV);
>
> Stealing the A15MPCORE device for a7 is kind of ugly, but I can't
> decide what would be better instead...
>

I agree, but I looked through the RMs for both and didn't find any
software-visible differences that would warrant crea

Re: [Qemu-devel] [PATCH 17/17] Implement support for i.MX7 Sabre board

2017-10-09 Thread Andrey Smirnov
On Fri, Oct 6, 2017 at 7:42 AM, Peter Maydell  wrote:
> On 18 September 2017 at 20:51, Andrey Smirnov  
> wrote:
>> Cc: Peter Maydell 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  hw/arm/Makefile.objs   |   2 +-
>>  hw/arm/mcimx7d-sabre.c | 100 
>> +
>>  2 files changed, 101 insertions(+), 1 deletion(-)
>>  create mode 100644 hw/arm/mcimx7d-sabre.c
>>
>> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
>> index 33f6051ae3..fc4a963de8 100644
>> --- a/hw/arm/Makefile.objs
>> +++ b/hw/arm/Makefile.objs
>> @@ -19,5 +19,5 @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
>>  obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
>>  obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
>>  obj-$(CONFIG_MPS2) += mps2.o
>> -obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o
>> +obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
>>
>> diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
>> new file mode 100644
>> index 00..34e3933db8
>> --- /dev/null
>> +++ b/hw/arm/mcimx7d-sabre.c
>> @@ -0,0 +1,100 @@
>> +/*
>> + * Copyright (c) 2017, Impinj, Inc.
>> + *
>> + * MCIMX7D_SABRE Board System emulation.
>> + *
>> + * Author: Andrey Smirnov 
>> + *
>> + * This code is licensed under the GPL, version 2 or later.
>> + * See the file `COPYING' in the top level directory.
>> + *
>> + * It (partially) emulates a mcimx7d_sabre board, with a Freescale
>> + * i.MX7 SoC
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "qapi/error.h"
>> +#include "qemu-common.h"
>> +#include "hw/arm/fsl-imx7.h"
>> +#include "hw/boards.h"
>> +#include "sysemu/sysemu.h"
>> +#include "sysemu/device_tree.h"
>> +#include "qemu/error-report.h"
>> +#include "sysemu/qtest.h"
>> +#include "net/net.h"
>> +
>> +typedef struct {
>> +FslIMX7State soc;
>> +MemoryRegion ram;
>> +} MCIMX7Sabre;
>> +
>> +static void mcimx7d_add_psci_node(const struct arm_boot_info *boot_info, 
>> void *fdt)
>> +{
>> +const char comp[] = "arm,psci-0.2\0arm,psci";
>> +
>> +qemu_fdt_add_subnode(fdt, "/psci");
>> +qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
>> +qemu_fdt_setprop_string(fdt, "/psci", "method", "smc");
>> +}
>
> You shouldn't need this -- we should just be able to work with whatever
> the real hardware's device tree is. ("virt" is a special case because
> we create our own device tree there.)
>

Upstream kernel for i.MX7 relies on PSCI to support SMP and this is a
kind of DT fixup that would normally be done by a PSCI-compatible
bootloader. I can remove this code, but it would effectively disable
SMP on vanilla DT/kernel combos.

>> +
>> +static void mcimx7d_sabre_init(MachineState *machine)
>> +{
>> +static struct arm_boot_info boot_info;
>> +MCIMX7Sabre *s = g_new0(MCIMX7Sabre, 1);
>> +Object *soc;
>> +int i;
>> +
>> +if (machine->ram_size > FSL_IMX7_MMDC_SIZE) {
>> +error_report("RAM size " RAM_ADDR_FMT " above max supported (%08x)",
>> + machine->ram_size, FSL_IMX7_MMDC_SIZE);
>> +exit(1);
>> +}
>> +
>> +boot_info = (struct arm_boot_info) {
>> +.loader_start = FSL_IMX7_MMDC_ADDR,
>> +.board_id = -1,
>> +.ram_size = machine->ram_size,
>> +.kernel_filename = machine->kernel_filename,
>> +.kernel_cmdline = machine->kernel_cmdline,
>> +.initrd_filename = machine->initrd_filename,
>> +.nb_cpus = smp_cpus,
>> +.modify_dtb = mcimx7d_add_psci_node,
>> +};
>> +
>> +object_initialize(&s->soc, sizeof(s->soc), TYPE_FSL_IMX7);
>> +soc = OBJECT(&s->soc);
>> +object_property_add_child(OBJECT(machine), "soc", soc, &error_fatal);
>> +object_property_set_bool(soc, true, "realized", &error_fatal);
>> +
>> +memory_region_allocate_system_memory(&s->ram, NULL, "mcimx7d-sabre.ram",
>> + machine->ram_size);
>> +memory_region_add_subregion(get_system_memory(),
>> +FSL_I

Re: [PATCH v1 3/5] contrib/gitdm: add Andrey to the individual group

2019-10-14 Thread Andrey Smirnov
On Mon, Oct 14, 2019 at 6:59 AM Alex Bennée  wrote:
>
> Please confirm this is the correct section for you.
>

I think this is. Here's

Acked-by: Andrey Smirnov 

in case that's needed.

> Signed-off-by: Alex Bennée 
> Cc: Andrey Smirnov 
> ---
>  contrib/gitdm/group-map-individuals | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/contrib/gitdm/group-map-individuals 
> b/contrib/gitdm/group-map-individuals
> index 301071b98b..624e27fc83 100644
> --- a/contrib/gitdm/group-map-individuals
> +++ b/contrib/gitdm/group-map-individuals
> @@ -18,3 +18,4 @@ e.emanuelegiuse...@gmail.com
>  dirty.ice...@gmail.com
>  liq...@163.com
>  liq...@gmail.com
> +andrew.smir...@gmail.com
> --
> 2.20.1
>



Re: [Qemu-devel] [PATCH 0/5] Various i.MX7 fixes

2019-06-17 Thread Andrey Smirnov
On Mon, Apr 15, 2019 at 6:39 PM Andrey Smirnov  wrote:
>
> Everyone:
>
> I recently revisited my i.MX7 work and this series contains all of the
> fixes I had to make to get it to work with latest (5.1-rc1) Linux
> kernel again as well as fixes for genuine bugs that I somehow missed
> during original submission ("pci: designware" patches). Hopefully each
> patch is self-explanatory.
>
> Feedback is welcome!
>

Is there any changes necessary for this to go in?

Thanks,
Andrey Smirnov



[Qemu-devel] [PATCH 5/5] i.mx7d: pci: Update PCI IRQ mapping to match HW

2019-04-15 Thread Andrey Smirnov
Datasheet for i.MX7 is incorrect and i.MX7's PCI IRQ mapping matches
that of i.MX6:

* INTD/MSI122
* INTC123
* INTB124
* INTA125

Fix all of the relevant code to reflect that fact. Needed by latest
Linux kernels.

Signed-off-by: Andrey Smirnov 
Cc: Peter Maydell 
Cc: Michael S. Tsirkin 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
---
 include/hw/arm/fsl-imx7.h | 8 
 hw/pci-host/designware.c  | 6 --
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
index 3efa697adc..9750003a4f 100644
--- a/include/hw/arm/fsl-imx7.h
+++ b/include/hw/arm/fsl-imx7.h
@@ -213,10 +213,10 @@ enum FslIMX7IRQs {
 FSL_IMX7_USB2_IRQ = 42,
 FSL_IMX7_USB3_IRQ = 40,
 
-FSL_IMX7_PCI_INTA_IRQ = 122,
-FSL_IMX7_PCI_INTB_IRQ = 123,
-FSL_IMX7_PCI_INTC_IRQ = 124,
-FSL_IMX7_PCI_INTD_IRQ = 125,
+FSL_IMX7_PCI_INTA_IRQ = 125,
+FSL_IMX7_PCI_INTB_IRQ = 124,
+FSL_IMX7_PCI_INTC_IRQ = 123,
+FSL_IMX7_PCI_INTD_IRQ = 122,
 
 FSL_IMX7_UART7_IRQ= 126,
 
diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
index e80facc4a0..f4c58b25c1 100644
--- a/hw/pci-host/designware.c
+++ b/hw/pci-host/designware.c
@@ -50,6 +50,8 @@
 #define DESIGNWARE_PCIE_ATU_DEVFN(x)   (((x) >> 16) & 0xff)
 #define DESIGNWARE_PCIE_ATU_UPPER_TARGET   0x91C
 
+#define DESIGNWARE_PCIE_IRQ_MSI3
+
 static DesignwarePCIEHost *
 designware_pcie_root_to_host(DesignwarePCIERoot *root)
 {
@@ -66,7 +68,7 @@ static void designware_pcie_root_msi_write(void *opaque, 
hwaddr addr,
 root->msi.intr[0].status |= BIT(val) & root->msi.intr[0].enable;
 
 if (root->msi.intr[0].status & ~root->msi.intr[0].mask) {
-qemu_set_irq(host->pci.irqs[0], 1);
+qemu_set_irq(host->pci.irqs[DESIGNWARE_PCIE_IRQ_MSI], 1);
 }
 }
 
@@ -310,7 +312,7 @@ static void designware_pcie_root_config_write(PCIDevice *d, 
uint32_t address,
 case DESIGNWARE_PCIE_MSI_INTR0_STATUS:
 root->msi.intr[0].status ^= val;
 if (!root->msi.intr[0].status) {
-qemu_set_irq(host->pci.irqs[0], 0);
+qemu_set_irq(host->pci.irqs[DESIGNWARE_PCIE_IRQ_MSI], 0);
 }
 break;
 
-- 
2.20.1




[Qemu-devel] [PATCH 0/5] Various i.MX7 fixes

2019-04-15 Thread Andrey Smirnov
Everyone:

I recently revisited my i.MX7 work and this series contains all of the
fixes I had to make to get it to work with latest (5.1-rc1) Linux
kernel again as well as fixes for genuine bugs that I somehow missed
during original submission ("pci: designware" patches). Hopefully each
patch is self-explanatory.

Feedback is welcome!

Thanks,
Andrey Smirnov

Andrey Smirnov (5):
  i.mx7d: Add no-op/unimplemented APBH DMA module
  i.mx7d: Add no-op/unimplemented PCIE PHY IP block
  pci: designware: Update MSI mapping unconditionally
  pci: designware: Update MSI mapping when MSI address changes
  i.mx7d: pci: Update PCI IRQ mapping to match HW

 include/hw/arm/fsl-imx7.h | 14 ++
 hw/arm/fsl-imx7.c | 11 +++
 hw/pci-host/designware.c  | 18 --
 3 files changed, 29 insertions(+), 14 deletions(-)

-- 
2.20.1




[Qemu-devel] [PATCH 1/5] i.mx7d: Add no-op/unimplemented APBH DMA module

2019-04-15 Thread Andrey Smirnov
Instantiate no-op APBH DMA module. Needed to boot latest Linux kernel.

Signed-off-by: Andrey Smirnov 
Cc: Peter Maydell 
Cc: Michael S. Tsirkin 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
---
 include/hw/arm/fsl-imx7.h | 3 +++
 hw/arm/fsl-imx7.c | 6 ++
 2 files changed, 9 insertions(+)

diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
index d848262bfd..aae4f860fc 100644
--- a/include/hw/arm/fsl-imx7.h
+++ b/include/hw/arm/fsl-imx7.h
@@ -179,6 +179,9 @@ enum FslIMX7MemoryMap {
 FSL_IMX7_PCIE_REG_SIZE= 16 * 1024,
 
 FSL_IMX7_GPR_ADDR = 0x3034,
+
+FSL_IMX7_DMA_APBH_ADDR= 0x3300,
+FSL_IMX7_DMA_APBH_SIZE= 0x2000,
 };
 
 enum FslIMX7IRQs {
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index 7663ad6861..1abfa5910c 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -526,6 +526,12 @@ static void fsl_imx7_realize(DeviceState *dev, Error 
**errp)
  */
 create_unimplemented_device("lcdif", FSL_IMX7_LCDIF_ADDR,
 FSL_IMX7_LCDIF_SIZE);
+
+/*
+ * DMA APBH
+ */
+create_unimplemented_device("dma-apbh", FSL_IMX7_DMA_APBH_ADDR,
+FSL_IMX7_DMA_APBH_SIZE);
 }
 
 static void fsl_imx7_class_init(ObjectClass *oc, void *data)
-- 
2.20.1




[Qemu-devel] [PATCH 2/5] i.mx7d: Add no-op/unimplemented PCIE PHY IP block

2019-04-15 Thread Andrey Smirnov
Add no-op/unimplemented PCIE PHY IP block. Needed by new kernels to
use PCIE.

Signed-off-by: Andrey Smirnov 
Cc: Peter Maydell 
Cc: Michael S. Tsirkin 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
---
 include/hw/arm/fsl-imx7.h | 3 +++
 hw/arm/fsl-imx7.c | 5 +
 2 files changed, 8 insertions(+)

diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
index aae4f860fc..3efa697adc 100644
--- a/include/hw/arm/fsl-imx7.h
+++ b/include/hw/arm/fsl-imx7.h
@@ -125,6 +125,9 @@ enum FslIMX7MemoryMap {
 FSL_IMX7_ADC2_ADDR= 0x3062,
 FSL_IMX7_ADCn_SIZE= 0x1000,
 
+FSL_IMX7_PCIE_PHY_ADDR= 0x306D,
+FSL_IMX7_PCIE_PHY_SIZE= 0x1,
+
 FSL_IMX7_GPC_ADDR = 0x303A,
 
 FSL_IMX7_I2C1_ADDR= 0x30A2,
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index 1abfa5910c..813fb55ca9 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -532,6 +532,11 @@ static void fsl_imx7_realize(DeviceState *dev, Error 
**errp)
  */
 create_unimplemented_device("dma-apbh", FSL_IMX7_DMA_APBH_ADDR,
 FSL_IMX7_DMA_APBH_SIZE);
+/*
+ * PCIe PHY
+ */
+create_unimplemented_device("pcie-phy", FSL_IMX7_PCIE_PHY_ADDR,
+FSL_IMX7_PCIE_PHY_SIZE);
 }
 
 static void fsl_imx7_class_init(ObjectClass *oc, void *data)
-- 
2.20.1




[Qemu-devel] [PATCH 3/5] pci: designware: Update MSI mapping unconditionally

2019-04-15 Thread Andrey Smirnov
Expression to calculate update_msi_mapping in code handling writes to
DESIGNWARE_PCIE_MSI_INTR0_ENABLE is missing an ! operator and should
be:

!!root->msi.intr[0].enable ^ !!val;

so that MSI mapping is updated when enabled transitions from either
"none" -> "any" or "any" -> "none". Since that register shouldn't be
written to very often, change the code to update MSI mapping
unconditionally instead of trying to fix the update_msi_mapping logic.

Signed-off-by: Andrey Smirnov 
Cc: Peter Maydell 
Cc: Michael S. Tsirkin 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
---
 hw/pci-host/designware.c | 10 ++
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
index 29ea313798..6affe823c0 100644
--- a/hw/pci-host/designware.c
+++ b/hw/pci-host/designware.c
@@ -296,16 +296,10 @@ static void designware_pcie_root_config_write(PCIDevice 
*d, uint32_t address,
 root->msi.base |= (uint64_t)val << 32;
 break;
 
-case DESIGNWARE_PCIE_MSI_INTR0_ENABLE: {
-const bool update_msi_mapping = !root->msi.intr[0].enable ^ !!val;
-
+case DESIGNWARE_PCIE_MSI_INTR0_ENABLE:
 root->msi.intr[0].enable = val;
-
-if (update_msi_mapping) {
-designware_pcie_root_update_msi_mapping(root);
-}
+designware_pcie_root_update_msi_mapping(root);
 break;
-}
 
 case DESIGNWARE_PCIE_MSI_INTR0_MASK:
 root->msi.intr[0].mask = val;
-- 
2.20.1




[Qemu-devel] [PATCH 4/5] pci: designware: Update MSI mapping when MSI address changes

2019-04-15 Thread Andrey Smirnov
MSI mapping needs to be update when MSI address changes, so add the
code to do so.

Signed-off-by: Andrey Smirnov 
Cc: Peter Maydell 
Cc: Michael S. Tsirkin 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
---
 hw/pci-host/designware.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
index 6affe823c0..e80facc4a0 100644
--- a/hw/pci-host/designware.c
+++ b/hw/pci-host/designware.c
@@ -289,11 +289,13 @@ static void designware_pcie_root_config_write(PCIDevice 
*d, uint32_t address,
 case DESIGNWARE_PCIE_MSI_ADDR_LO:
 root->msi.base &= 0xULL;
 root->msi.base |= val;
+designware_pcie_root_update_msi_mapping(root);
 break;
 
 case DESIGNWARE_PCIE_MSI_ADDR_HI:
 root->msi.base &= 0xULL;
 root->msi.base |= (uint64_t)val << 32;
+designware_pcie_root_update_msi_mapping(root);
 break;
 
 case DESIGNWARE_PCIE_MSI_INTR0_ENABLE:
-- 
2.20.1




Re: [Qemu-devel] Maintainers, please tell us how to boot your machines!

2019-04-15 Thread Andrey Smirnov
On Tue, Mar 12, 2019 at 10:36 AM Markus Armbruster  wrote:
>
> Dear board code maintainers,
>
> This is a (rather late) follow-up to the last QEMU summit.  Minutes[*]:
>
>  * Deprecating unmaintained features (devices, targets, backends) in QEMU
>
>QEMU has a mechanism to deprecate features but there remains a lot of
>old unmaintained code.  Refactoring is hindered by untested legacy
>code, so there is a desire to deprecate unmaintained features more
>often.
>
>[...]
>
>We should require at least a minimal test for each board; if nobody
>cares enough to come up with one, that board should be deprecated.
>
>[...]
>
>Also see the qemu-devel discussion about deprecating code:
>https://lists.nongnu.org/archive/html/qemu-devel/2018-10/msg05828.html.
>
> That's a link to "Minutes of KVM Forum BoF on deprecating stuff".
> Quote:
>
>  * One obvious class of candidates for removal is machines we don't know
>how to boot, or can't boot, say because we lack required firmware
>and/or OS.
>
>Of course, "can boot" should be an automated test.  As a first step
>towards that, we should at least document how to boot each machine.
>We're going to ask machine maintainers to do that.
>
> Let's get going on this.
>
> I gathered the machine types, mapped them to source files, which I fed
> to get_maintainer.pl.  Results are appended.  If you're cc'ed,
> MAINTAINERS fingers you for at least one machine type's source file.
> Please tell us for all of them how to to a "meaningful" boot test.
>
> For now, what's "meaningful" is entirely up to you.  Booting Linux
> certainly is.
>
> Make sure to include a complete QEMU command line.  If your QEMU command
> line requires resources beyond the QEMU source tree and what we build
> from it, please detail them, and provide download URLs as far as
> possible.
>
> Goals for this exercise:
>
> * Gather information we need to cover more machines in our automated
>   testing.
>
>   Related work:
>   [PATCH v4 00/19] Acceptance Tests: target architecture support
>   Message-Id: <20190312121150.8638-1-cr...@redhat.com>
>   https://lists.gnu.org/archive/html/qemu-devel/2019-03/msg03881.html
>
> * Maybe identify a few machines we don't know how to boot anymore.
>
> Thanks in advance for your help!
>
>
>
> Machines with at least one maintainer:
>
>
> = hw/arm/mcimx7d-sabre.c =
> Peter Maydell  (odd fixer:MCIMX7D SABRE / i...)
> Andrey Smirnov  (reviewer:MCIMX7D SABRE / i...)
> qemu-...@nongnu.org (open list:MCIMX7D SABRE / i...)
>

Sorry I am late to this party. I haven't used i.MX7 emulation in a
while and things didn't go smoothly out of the box, so I had to create
a number of fixes (submitted to the ML).

I use Linux kernel built using Buildroot for validation. Buildroot
should have a default i.MX7 Sabred SD configuration and that should
probably work. I usually change mine slightly to use compiled-in
rootfs to simplify storage setup.

In case this is helpful here's a number of commands I use to start my
test cases:

* PCIe (e1000 ethernet attached), USB (usb stick attached), SD:
arm-softmmu/qemu-system-arm -smp 2 -m 1024 -machine mcimx7d-sabre
-nographic -serial mon:stdio -kernel  -dtb  -device e1000e,bus="dw-pcie",netdev=lan0 -netdev
tap,id=lan0,ifname=tap0,script=no,downscript=no -append
"console=ttymxc0,115200 noinitrd" -usb -drive
if=none,id=stick,file=,format=raw -device
usb-storage,bus=usb-bus.0,drive=stick -drive
id=sd1,if=sd,format=file,file= -drive
id=sd2,if=sd,format=file,file= -driv
eid=sd3,if=sd,format=file,file=

* EHCI USB attached via PCIe with legacy interrupts, Ethernet
connected to built-in controller:
arm-softmmu/qemu-system-arm -smp 2 -m 1024 -machine mcimx7d-sabre
-nographic -serial mon:stdio -kernel  -dtb  -device usb-ehci,id=ehci,bus="dw-pcie" -net
nic,model=imx.fec,netdev=lan0 -netdev
tap,id=lan0,ifname=tap0,script=no,downscript=no -append
"console=ttymxc0,115200 noinitrd pci=nomsi" -usb -drive
if=none,id=stick,file=,format=raw

Also, I don't think anyone would try to do this, but just as a
warning, building QEMU with --enable-tcg-interpreter doesn't really
work that well (/init gets SIGKILLed every time), so I'd recommend
avoiding using that option.

Hopefully this is enough info, but if not, feel free to ask me more questions.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH v2] i.MX: Fix FEC/ENET receive funtions

2018-01-22 Thread Andrey Smirnov
On Mon, Jan 22, 2018 at 3:48 AM, Peter Maydell  wrote:
> On 13 January 2018 at 11:34, Jean-Christophe Dubois  
> wrote:
>> The actual imx_eth_enable_rx() function is buggy.
>>
>> It updates s->regs[ENET_RDAR] after calling qemu_flush_queued_packets().
>>
>> qemu_flush_queued_packets() is going to call imx_XXX_receive() which itself
>> is going to call imx_eth_enable_rx().
>>
>> By updating s->regs[ENET_RDAR] after calling qemu_flush_queued_packets()
>> we end up updating the register with an outdated value which might
>> lead to disabling the receive function in the i.MX FEC/ENET device.
>>
>> This patch change the place where the register update is done so that the
>> register value stays up to date and the receive function can keep
>> running.
>>
>> Reported-by: Fyleo 
>> Tested-by: Fyleo  
>> Signed-off-by: Jean-Christophe Dubois 
>> ---
>
> Andrey, do you have an opinion on this patch, since you've been
> looking at i.MX code recently?
>

The rationale makes sense to me and patch looks like a good cleanup in
general, so FWIW:

Reviewed-by: Andrey Smirnov 

I also gave it a spin against my i.MX7 changes with doing basic things
like ping and scp of 1GB file, so I can give my:

Tested-by: Andrey Smirnov 

for that.

Thanks,
Andrey Smirnov


>> Change since v1:
>> 1. Rebase the patch on the updated master branch
>>
>>  hw/net/imx_fec.c | 8 ++--
>>  1 file changed, 2 insertions(+), 6 deletions(-)
>>
>> diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
>> index 4fb48f62ba..9506f9b69f 100644
>> --- a/hw/net/imx_fec.c
>> +++ b/hw/net/imx_fec.c
>> @@ -595,19 +595,16 @@ static void imx_eth_do_tx(IMXFECState *s, uint32_t 
>> index)
>>  static void imx_eth_enable_rx(IMXFECState *s, bool flush)
>>  {
>>  IMXFECBufDesc bd;
>> -bool rx_ring_full;
>>
>>  imx_fec_read_bd(&bd, s->rx_descriptor);
>>
>> -rx_ring_full = !(bd.flags & ENET_BD_E);
>> +s->regs[ENET_RDAR] = (bd.flags & ENET_BD_E) ? ENET_RDAR_RDAR : 0;
>>
>> -if (rx_ring_full) {
>> +if (!s->regs[ENET_RDAR]) {
>>  FEC_PRINTF("RX buffer full\n");
>>  } else if (flush) {
>>  qemu_flush_queued_packets(qemu_get_queue(s->nic));
>>  }
>> -
>> -s->regs[ENET_RDAR] = rx_ring_full ? 0 : ENET_RDAR_RDAR;
>>  }
>>
>>  static void imx_eth_reset(DeviceState *d)
>> @@ -866,7 +863,6 @@ static void imx_eth_write(void *opaque, hwaddr offset, 
>> uint64_t value,
>>  case ENET_RDAR:
>>  if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) {
>>  if (!s->regs[index]) {
>> -s->regs[index] = ENET_RDAR_RDAR;
>>  imx_eth_enable_rx(s, true);
>>  }
>>  } else {
>> --
>> 2.14.1
>
> Reviewed-by: Peter Maydell 
>
> thanks
> -- PMM



[Qemu-devel] [PATCH 1/2] char: i.MX: Simplify imx_update()

2018-03-15 Thread Andrey Smirnov
Code of imx_update() is slightly confusing since the "flags" variable
doesn't really corespond to anything in real hardware and server as a
kitchensink accumulating events normally reported via USR1 and USR2
registers.

Change the code to explicitly evaluate state of interrupts reported
via USR1 and USR2 against corresponding masking bits and use the to
detemine if IRQ line should be asserted or not.

NOTE: Check for UTS1_TXEMPTY being set has been dropped for two
reasons:

1. Emulation code implements a single character FIFO, so this flag
   will always be set since characters are trasmitted as a part of
   the code emulating "push" into the FIFO

2. imx_update() is really just a function doing ORing and maksing
   of reported events, so checking for UTS1_TXEMPTY should happen,
   if it's ever really needed should probably happen outside of
   it.

Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: Bill Paul 
Cc: Peter Maydell 
Signed-off-by: Andrey Smirnov 
---
 hw/char/imx_serial.c | 24 
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index 70405ccf8b..d1e8586280 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -56,16 +56,24 @@ static const VMStateDescription vmstate_imx_serial = {
 
 static void imx_update(IMXSerialState *s)
 {
-uint32_t flags;
+uint32_t usr1;
+uint32_t usr2;
+uint32_t mask;
 
-flags = (s->usr1 & s->ucr1) & (USR1_TRDY|USR1_RRDY);
-if (s->ucr1 & UCR1_TXMPTYEN) {
-flags |= (s->uts1 & UTS1_TXEMPTY);
-} else {
-flags &= ~USR1_TRDY;
-}
+/*
+ * Lucky for us TRDY and RRDY has the same offset in both USR1 and
+ * UCR1, so we can get away with something as simple as the
+ * following:
+ */
+usr1 = s->usr1 & s->ucr1 & (USR1_TRDY | USR1_RRDY);
+/*
+ * Bits that we want in USR2 are not as conveniently laid out,
+ * unfortunately.
+ */
+mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0;
+usr2 = s->usr2 & mask;
 
-qemu_set_irq(s->irq, !!flags);
+qemu_set_irq(s->irq, usr1 || usr2);
 }
 
 static void imx_serial_reset(IMXSerialState *s)
-- 
2.14.3




[Qemu-devel] [PATCH 2/2] char: i.MX: Add support for "TX complete" interrupt

2018-03-15 Thread Andrey Smirnov
Add support for "TX complete"/TXDC interrupt generate by real HW since
it is needed to support guests other than Linux.

Based on the patch by Bill Paul as found here:
https://bugs.launchpad.net/qemu/+bug/1753314

Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: Bill Paul 
Cc: Peter Maydell 
Signed-off-by: Andrey Smirnov 
---

Bill:

I only tested this with i.MX7/Linux guest combo and am hoping you can
take this and previous patch and give it a try on your VxWorks setup.

Peter:

Bill is the author of original code, so I am not sure how to handle
Signed-off-by from him. I'd like to add it to this patch, but since
his original submission to launchpad didn't have one it is currently
omitted.

 include/hw/char/imx_serial.h |  3 +++
 hw/char/imx_serial.c | 20 +---
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/include/hw/char/imx_serial.h b/include/hw/char/imx_serial.h
index baeec3183f..5b99cee7cf 100644
--- a/include/hw/char/imx_serial.h
+++ b/include/hw/char/imx_serial.h
@@ -67,6 +67,8 @@
 #define UCR2_RXEN   (1<<1)/* Receiver enable */
 #define UCR2_SRST   (1<<0)/* Reset complete */
 
+#define UCR4_TCEN   BIT(3)/* TX complete interrupt enable */
+
 #define UTS1_TXEMPTY(1<<6)
 #define UTS1_RXEMPTY(1<<5)
 #define UTS1_TXFULL (1<<4)
@@ -95,6 +97,7 @@ typedef struct IMXSerialState {
 uint32_t ubmr;
 uint32_t ubrc;
 uint32_t ucr3;
+uint32_t ucr4;
 
 qemu_irq irq;
 CharBackend chr;
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index d1e8586280..1e5540472b 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -37,8 +37,8 @@
 
 static const VMStateDescription vmstate_imx_serial = {
 .name = TYPE_IMX_SERIAL,
-.version_id = 1,
-.minimum_version_id = 1,
+.version_id = 2,
+.minimum_version_id = 2,
 .fields = (VMStateField[]) {
 VMSTATE_INT32(readbuff, IMXSerialState),
 VMSTATE_UINT32(usr1, IMXSerialState),
@@ -50,6 +50,7 @@ static const VMStateDescription vmstate_imx_serial = {
 VMSTATE_UINT32(ubmr, IMXSerialState),
 VMSTATE_UINT32(ubrc, IMXSerialState),
 VMSTATE_UINT32(ucr3, IMXSerialState),
+VMSTATE_UINT32(ucr4, IMXSerialState),
 VMSTATE_END_OF_LIST()
 },
 };
@@ -71,6 +72,11 @@ static void imx_update(IMXSerialState *s)
  * unfortunately.
  */
 mask = (s->ucr1 & UCR1_TXMPTYEN) ? USR2_TXFE : 0;
+/*
+ * TCEN and TXDC are both bit 3
+ */
+mask |= s->ucr4 & UCR4_TCEN;
+
 usr2 = s->usr2 & mask;
 
 qemu_set_irq(s->irq, usr1 || usr2);
@@ -163,6 +169,8 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
 return s->ucr3;
 
 case 0x23: /* UCR4 */
+return s->ucr4;
+
 case 0x29: /* BRM Incremental */
 return 0x0; /* TODO */
 
@@ -191,8 +199,10 @@ static void imx_serial_write(void *opaque, hwaddr offset,
  * qemu_chr_fe_write and background I/O callbacks */
 qemu_chr_fe_write_all(&s->chr, &ch, 1);
 s->usr1 &= ~USR1_TRDY;
+s->usr2 &= ~USR2_TXDC;
 imx_update(s);
 s->usr1 |= USR1_TRDY;
+s->usr2 |= USR2_TXDC;
 imx_update(s);
 }
 break;
@@ -265,8 +275,12 @@ static void imx_serial_write(void *opaque, hwaddr offset,
 s->ucr3 = value & 0x;
 break;
 
-case 0x2d: /* UTS1 */
 case 0x23: /* UCR4 */
+s->ucr4 = value & 0x;
+imx_update(s);
+break;
+
+case 0x2d: /* UTS1 */
 qemu_log_mask(LOG_UNIMP, "[%s]%s: Unimplemented reg 0x%"
   HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset);
 /* TODO */
-- 
2.14.3




Re: [Qemu-devel] [PATCH] fsl_etsec: Fix Tx BD ring wrapping handling

2017-01-04 Thread Andrey Smirnov
On Sun, Dec 25, 2016 at 8:12 PM, Jason Wang  wrote:
>
>
> On 2016年12月21日 05:11, Andrey Smirnov wrote:
>>
>> Current code that handles Tx buffer desciprtor ring scanning employs the
>> following algorithm:
>>
>> 1. Restore current buffer descriptor pointer from TBPTRn
>>
>> 2. Process current descriptor
>>
>> 3. If current descriptor has BD_WRAP flag set set current
>>descriptor pointer to start of the descriptor ring
>>
>> 4. If current descriptor points to start of the ring exit the
>>loop, otherwise increment current descriptor pointer and go
>>to #2
>>
>> 5. Store current descriptor in TBPTRn
>>
>> As it can be seen the way the code is implemented results in buffer
>> descriptor ring being scanned starting at offset/descriptor #0. While
>> covering proverbial "99%" of the cases, this algorithm becomes
>> problematic for a number of edge cases.
>>
>> Consider the following scenario: guest OS driver initializes descriptor
>> ring to N individual descriptors and starts sending data out. Depending
>> on the volume of traffic and probably guest OS driver implementation it
>> is possible that an edge case where a packet, spread across 2
>> descriptors is placed in descriptors N - 1 and 0 in that order(it is
>> easy to imagine similar examples involving more than 2 descriptors).
>>
>> What happens then is aforementioned algorithm starts at descriptor 0,
>> sees a descriptor marked as BD_LAST, which it happily sends out as a
>> separate packet(very much malformed at this point) then the iteration
>> continues and the first part of the original packet is tacked to the
>> next transmission which ends up being bogus as well.
>>
>> This behvaiour can be pretty reliably observed when scp'ing data from a
>> guest OS via TAP interface for files larger than 160K (every time for
>> 700K+).
>>
>> This patch changes the scanning algorithm to do the following:
>>
>> 1. Restore "current" and "start" buffer descriptor pointer from
>>TBPTRn
>>
>> 2. If "current" descriptor has BD_WRAP flag set "next"
>>descriptor pointer to start of the descriptor ring otherwise
>>set "next" to descriptor right after "current"
>>
>> 3. Process current descriptor
>>
>> 4. If current descriptore has BD_LAST(end of a packet) set save
>>"next" descriptor pointer in TBPTRn
>>
>> 5. Set "current" descriptor pointer to "next"
>>
>> 6. If "current" descriptor points to "start" (from #1) exit the
>> loop
>>loop, otherwise go to #2
>
>
> Hi, I'm not familiar with this card but this seems could be simply addressed
> by exiting the loop when bd_flags != BD_TX_READY instead of bd_addr !=
> ring_base (which seems buggy for heavy load)?

This would change the emulated behavior, since original implementation
would scan the entirety of buffer descriptor ring and process every
entry with "READY" bit set regardless if those descriptors were placed
right after each other or had gaps.

That being said, I don't have any reason to believe that
aforementioned peculiarity is correct behavior that actual HW would
exhibit. I can't seem to find any detailed description of what goes
under the hood in RM except for this:

"... The TBPTR register is internally written by the eTSEC’s DMA
controller during transmission. The pointer increments by eight
(bytes) each time a descriptor is closed successfully by the eTSEC..."

And reading that seems to suggest, that what you are proposing,
besides being simpler solution, might also be the correct way to
emulate this aspect of eTSEC's DMA engine behavior.

Let me experiment and see if encounter any problems with this
approach. I'll post updated version of the patch if it works out.

Thanks,
Andrey Smirnov



[Qemu-devel] [PATCH v2] fsl_etsec: Fix Tx BD ring wrapping handling

2017-01-05 Thread Andrey Smirnov
Current code that handles Tx buffer desciprtor ring scanning employs the
following algorithm:

1. Restore current buffer descriptor pointer from TBPTRn

2. Process current descriptor

3. If current descriptor has BD_WRAP flag set set current
   descriptor pointer to start of the descriptor ring

4. If current descriptor points to start of the ring exit the
   loop, otherwise increment current descriptor pointer and go
   to #2

5. Store current descriptor in TBPTRn

The way the code is implemented results in buffer descriptor ring being
scanned starting at offset/descriptor #0. While covering 99% of the
cases, this algorithm becomes problematic for a number of edge cases.

Consider the following scenario: guest OS driver initializes descriptor
ring to N individual descriptors and starts sending data out. Depending
on the volume of traffic and probably guest OS driver implementation it
is possible that an edge case where a packet, spread across 2
descriptors is placed in descriptors N - 1 and 0 in that order(it is
easy to imagine similar examples involving more than 2 descriptors).

What happens then is aforementioned algorithm starts at descriptor 0,
sees a descriptor marked as BD_LAST, which it happily sends out as a
separate packet(very much malformed at this point) then the iteration
continues and the first part of the original packet is tacked to the
next transmission which ends up being bogus as well.

This behvaiour can be pretty reliably observed when scp'ing data from a
guest OS via TAP interface for files larger than 160K (every time for
700K+).

This patch changes the scanning algorithm to do the following:

1. Restore "current" buffer descriptor pointer from
   TBPTRn

2. If "current" descriptor does not have BD_TX_READY set, goto #6

3. Process current descriptor

4. If "current" descriptor has BD_WRAP flag set "current"
   descriptor pointer to start of the descriptor ring otherwise
   set increment "current" by the size of one descriptor

5. Goto #1

6. Save "current" buffer descriptor in TBPTRn

This way we preserve the information about which descriptor was
processed last and always start where we left off avoiding the original
problem. On top of that, judging by the following excerpt from
MPC8548ERM (p. 14-48):

"... When the end of the TxBD ring is reached, eTSEC initializes TBPTRn
to the value in the corresponding TBASEn. The TBPTR register is
internally written by the eTSEC’s DMA controller during
transmission. The pointer increments by eight (bytes) each time a
descriptor is closed successfully by the eTSEC..."

revised algorithm might also a more correct way of emulating this aspect
of eTSEC peripheral.

Cc: Alexander Graf 
Cc: Scott Wood 
Cc: Jason Wang 
Cc: qemu-devel@nongnu.org
Signed-off-by: Andrey Smirnov 
---

Changes since v2:

- Simplified new algorithm as per Jason Wang's suggestion

 hw/net/fsl_etsec/rings.c | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/hw/net/fsl_etsec/rings.c b/hw/net/fsl_etsec/rings.c
index 54c0127..d764b1c 100644
--- a/hw/net/fsl_etsec/rings.c
+++ b/hw/net/fsl_etsec/rings.c
@@ -358,12 +358,12 @@ void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr)
 /* Save flags before BD update */
 bd_flags = bd.flags;
 
-if (bd_flags & BD_TX_READY) {
-process_tx_bd(etsec, &bd);
+if (!(bd_flags & BD_TX_READY))
+break;
 
-/* Write back BD after update */
-write_buffer_descriptor(etsec, bd_addr, &bd);
-}
+process_tx_bd(etsec, &bd);
+/* Write back BD after update */
+write_buffer_descriptor(etsec, bd_addr, &bd);
 
 /* Wrap or next BD */
 if (bd_flags & BD_WRAP) {
@@ -371,12 +371,10 @@ void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr)
 } else {
 bd_addr += sizeof(eTSEC_rxtx_bd);
 }
+} while (TRUE);
 
-} while (bd_addr != ring_base);
-
-bd_addr = ring_base;
-
-/* Save the Buffer Descriptor Pointers to current bd */
+/* Save the Buffer Descriptor Pointers to last bd that was not
+ * succesfully closed */
 etsec->regs[TBPTR0 + ring_nbr].value = bd_addr;
 
 /* Set transmit halt THLTx */
-- 
2.9.3




[Qemu-devel] [PATCH v3] fsl_etsec: Fix Tx BD ring wrapping handling

2017-01-05 Thread Andrey Smirnov
Current code that handles Tx buffer desciprtor ring scanning employs the
following algorithm:

1. Restore current buffer descriptor pointer from TBPTRn

2. Process current descriptor

3. If current descriptor has BD_WRAP flag set set current
   descriptor pointer to start of the descriptor ring

4. If current descriptor points to start of the ring exit the
   loop, otherwise increment current descriptor pointer and go
   to #2

5. Store current descriptor in TBPTRn

The way the code is implemented results in buffer descriptor ring being
scanned starting at offset/descriptor #0. While covering 99% of the
cases, this algorithm becomes problematic for a number of edge cases.

Consider the following scenario: guest OS driver initializes descriptor
ring to N individual descriptors and starts sending data out. Depending
on the volume of traffic and probably guest OS driver implementation it
is possible that an edge case where a packet, spread across 2
descriptors is placed in descriptors N - 1 and 0 in that order(it is
easy to imagine similar examples involving more than 2 descriptors).

What happens then is aforementioned algorithm starts at descriptor 0,
sees a descriptor marked as BD_LAST, which it happily sends out as a
separate packet(very much malformed at this point) then the iteration
continues and the first part of the original packet is tacked to the
next transmission which ends up being bogus as well.

This behvaiour can be pretty reliably observed when scp'ing data from a
guest OS via TAP interface for files larger than 160K (every time for
700K+).

This patch changes the scanning algorithm to do the following:

1. Restore "current" buffer descriptor pointer from
   TBPTRn

2. If "current" descriptor does not have BD_TX_READY set, goto #6

3. Process current descriptor

4. If "current" descriptor has BD_WRAP flag set "current"
   descriptor pointer to start of the descriptor ring otherwise
   set increment "current" by the size of one descriptor

5. Goto #1

6. Save "current" buffer descriptor in TBPTRn

This way we preserve the information about which descriptor was
processed last and always start where we left off avoiding the original
problem. On top of that, judging by the following excerpt from
MPC8548ERM (p. 14-48):

"... When the end of the TxBD ring is reached, eTSEC initializes TBPTRn
to the value in the corresponding TBASEn. The TBPTR register is
internally written by the eTSEC’s DMA controller during
transmission. The pointer increments by eight (bytes) each time a
descriptor is closed successfully by the eTSEC..."

revised algorithm might also a more correct way of emulating this aspect
of eTSEC peripheral.

Cc: Alexander Graf 
Cc: Scott Wood 
Cc: Jason Wang 
Cc: qemu-devel@nongnu.org
Signed-off-by: Andrey Smirnov 
---

Changes since v1:

- Simplified new algorithm as per Jason Wang's suggestion

Changes since v2:

- Fixed code style problems

 hw/net/fsl_etsec/rings.c | 19 +--
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/hw/net/fsl_etsec/rings.c b/hw/net/fsl_etsec/rings.c
index 54c0127..d0f93ee 100644
--- a/hw/net/fsl_etsec/rings.c
+++ b/hw/net/fsl_etsec/rings.c
@@ -358,25 +358,24 @@ void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr)
 /* Save flags before BD update */
 bd_flags = bd.flags;
 
-if (bd_flags & BD_TX_READY) {
-process_tx_bd(etsec, &bd);
-
-/* Write back BD after update */
-write_buffer_descriptor(etsec, bd_addr, &bd);
+if (!(bd_flags & BD_TX_READY)) {
+break;
 }
 
+process_tx_bd(etsec, &bd);
+/* Write back BD after update */
+write_buffer_descriptor(etsec, bd_addr, &bd);
+
 /* Wrap or next BD */
 if (bd_flags & BD_WRAP) {
 bd_addr = ring_base;
 } else {
 bd_addr += sizeof(eTSEC_rxtx_bd);
 }
+} while (TRUE);
 
-} while (bd_addr != ring_base);
-
-bd_addr = ring_base;
-
-/* Save the Buffer Descriptor Pointers to current bd */
+/* Save the Buffer Descriptor Pointers to last bd that was not
+ * succesfully closed */
 etsec->regs[TBPTR0 + ring_nbr].value = bd_addr;
 
 /* Set transmit halt THLTx */
-- 
2.9.3




[Qemu-devel] [PATCH] hw/arm: Allow manually specified /psci node

2018-04-02 Thread Andrey Smirnov
Change the code to avoid exiting QEMU if user provided DTB contains
manually specified /psci node and skip any /psci related fixups
instead.

Fixes: 4cbca7d9b4 ("hw/arm: Move virt's PSCI DT fixup code to
arm/boot.c")

Cc: Peter Maydell 
Cc: Marc Zyngier 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Signed-off-by: Andrey Smirnov 
---

Mark:

Sorry about the inconvenience, here's the fix (hopefully) to the
prolem you reported in [1]. Let me know if skipping all PSCI related
DTB fixup if /psic node is present is not the behaviour you had in
mind for your suggested fix.

Thanks,
Andrey Smirnov

[1] http://lists.gnu.org/archive/html/qemu-devel/2018-03/msg06914.html

 hw/arm/boot.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 6d0c92ab88..d9f9375cdb 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -422,6 +422,7 @@ static void fdt_add_psci_node(void *fdt)
 ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(0));
 const char *psci_method;
 int64_t psci_conduit;
+int rc;
 
 psci_conduit = object_property_get_int(OBJECT(armcpu),
"psci-conduit",
@@ -439,6 +440,15 @@ static void fdt_add_psci_node(void *fdt)
 g_assert_not_reached();
 }
 
+/*
+ * If /psci node is present in provided DTB, assume that no fixup
+ * is necessary and all PSCI configuration should be taken as-is
+ */
+rc = fdt_path_offset(fdt, "/psci");
+if (rc >= 0) {
+return;
+}
+
 qemu_fdt_add_subnode(fdt, "/psci");
 if (armcpu->psci_version == 2) {
 const char comp[] = "arm,psci-0.2\0arm,psci";
-- 
2.14.3




[Qemu-devel] [PATCH v2 00/27] Initial i.MX7 support

2017-10-23 Thread Andrey Smirnov
Hi everyone,

This v2 of the patch series containing the work that I've done in
order to enable support for i.MX7 emulation in QEMU.

As the one before last commit in the series states the supported i.MX7
features are:

* up to 2 Cortex A9 cores (SMP works with PSCI)
* A7 MPCORE (identical to A15 MPCORE)
* 4 GPTs modules
* 7 GPIO controllers
* 2 IOMUXC controllers
* 1 CCM module
* 1 SVNS module
* 1 SRC module
* 1 GPCv2 controller
* 4 eCSPI controllers
* 4 I2C controllers
* 7 i.MX UART controllers
* 2 FlexCAN controllers
* 2 Ethernet controllers (FEC)
* 3 SD controllers (USDHC)
* 4 WDT modules
* 1 SDMA module
* 1 GPR module
* 2 USBMISC modules
* 2 ADC modules
* 1 PCIe controller

Feedback is welcome!

Changes since [v1]:

- Patchset no longer relies on "ignore_memory_transaction_failures = false"
  for its functionality

- As a consequnce of implementing the above a number of patches
  implementing dummy IP block emulation as well as PCIe emulation
  patches that I alluded to in [v1] are now included in this patch
  series

- "has_el3" property is no longer being set to "false" as a part
  of intialization of A7 CPU. I couldn't reproduce the issues that
  I thought I was having, so I just dropped that code.

- A number of smaller feedback items from Peter and other has been
  incorporated into the patches.


Peter, I didn't hear anything from you about the code of
mcimx7d_add_psci_node(), as discussed here:

https://www.mail-archive.com/qemu-devel@nongnu.org/msg486874.html

so I kept the original code intact. As I mentioned before, my goal was
to be able to boot into vanilla Linux kerenel and have working SMP
without needing to use a PSCI implementing bootloader. If that is
something that new board code shouldn't do, please let me know.

Thanks,
Andrey Smirnov

[v1] https://lists.gnu.org/archive/html/qemu-devel/2017-09/msg04770.html

P.S.: I don't know the best way to specify mailing list message
archives, so if I did it wrong please let me know.

Andrey Smirnov (27):
  imx_fec: Do not link to netdev
  imx_fec: Refactor imx_eth_enable_rx()
  imx_fec: Change queue flushing heuristics
  imx_fec: Use ENET_FTRL to determine truncation length
  imx_fec: Use MIN instead of explicit ternary operator
  imx_fec: Emulate SHIFT16 in ENETx_RACC
  imx_fec: Add support for multiple Tx DMA rings
  imx_fec: Use correct length for packet size
  imx_fec: Fix a typo in imx_enet_receive()
  imx_fec: Reserve full 4K page for the register file
  sdhci: Add i.MX specific subtype of SDHCI
  sdhci: Implement write method of ACMD12ERRSTS register
  i.MX: Add code to emulate i.MX7 CCM, PMU and ANALOG IP blocks
  i.MX: Add code to emulate i.MX2 watchdog IP block
  i.MX: Add code to emulate i.MX7 SNVS IP-block
  i.MX: Add code to emulate GPCv2 IP block
  i.MX: Add code to emulate i.MX7 IOMUXC IP block
  i.MX: Add i.MX7 GPT variant
  i.MX: Add code to emulate SDMA IP block
  i.MX: Add code to emulate FlexCAN IP block
  i.MX: Add implementation of i.MX7 GPR IP block
  pci: Add support for Designware IP block
  i.MX: Add code to emulate i.MX7 USBMISC IP block
  i.MX: Add code to emulate i.MX7 ADC IP block
  i.MX: Add code to emulate i.MX7 SRC IP-block
  i.MX: Add i.MX7 SOC implementation.
  Implement support for i.MX7 Sabre board

 default-configs/arm-softmmu.mak  |   3 +
 hw/arm/Makefile.objs |   2 +
 hw/arm/fsl-imx6.c|   1 +
 hw/arm/fsl-imx7.c| 596 +
 hw/arm/mcimx7d-sabre.c   | 101 +++
 hw/dma/Makefile.objs |   1 +
 hw/dma/imx_sdma.c|  99 +++
 hw/intc/Makefile.objs|   2 +-
 hw/intc/imx_gpcv2.c  | 125 
 hw/misc/Makefile.objs|   8 +
 hw/misc/imx2_wdt.c   |  88 ++
 hw/misc/imx7_adc.c   |  99 +++
 hw/misc/imx7_ccm.c   | 233 +++
 hw/misc/imx7_gpr.c   | 119 
 hw/misc/imx7_iomuxc.c|  99 +++
 hw/misc/imx7_snvs.c  |  83 ++
 hw/misc/imx7_src.c   |  93 ++
 hw/misc/imx_flexcan.c|  99 +++
 hw/net/imx_fec.c | 163 ---
 hw/pci-host/Makefile.objs|   2 +
 hw/pci-host/designware.c | 614 +++
 hw/sd/sdhci-internal.h   |  15 +
 hw/sd/sdhci.c| 130 -
 hw/timer/imx_gpt.c   |  25 ++
 hw/usb/Makefile.objs |   1 +
 hw/usb/imx-usbmisc.c |  99 +++
 include/hw/arm/fsl-imx7.h| 217 ++
 include/hw/dma/imx_sdma.h|  22 ++
 include/hw/intc/imx_gpcv2.h  |  22 ++
 include/hw/misc/imx2_wdt.h   |  34 +++
 include/hw/misc/imx7_adc.h   |  22 ++
 include/hw/misc/imx7_ccm.h   | 130 +
 inc

[Qemu-devel] [PATCH v2 02/27] imx_fec: Refactor imx_eth_enable_rx()

2017-10-23 Thread Andrey Smirnov
Refactor imx_eth_enable_rx() to have more meaningfull variable name
than 'tmp' and to reduce number of logical negations done.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Reviewed-by: Peter Maydell 
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 88b4b049d7..8b2e4b8ffe 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -536,19 +536,19 @@ static void imx_eth_do_tx(IMXFECState *s)
 static void imx_eth_enable_rx(IMXFECState *s)
 {
 IMXFECBufDesc bd;
-bool tmp;
+bool rx_ring_full;
 
 imx_fec_read_bd(&bd, s->rx_descriptor);
 
-tmp = ((bd.flags & ENET_BD_E) != 0);
+rx_ring_full = !(bd.flags & ENET_BD_E);
 
-if (!tmp) {
+if (rx_ring_full) {
 FEC_PRINTF("RX buffer full\n");
 } else if (!s->regs[ENET_RDAR]) {
 qemu_flush_queued_packets(qemu_get_queue(s->nic));
 }
 
-s->regs[ENET_RDAR] = tmp ? ENET_RDAR_RDAR : 0;
+s->regs[ENET_RDAR] = rx_ring_full ? 0 : ENET_RDAR_RDAR;
 }
 
 static void imx_eth_reset(DeviceState *d)
-- 
2.13.5




[Qemu-devel] [PATCH v2 01/27] imx_fec: Do not link to netdev

2017-10-23 Thread Andrey Smirnov
Binding to a particular netdev doesn't seem to belong to this layer
and should probably be done as a part of board or SoC specific code.

Convert all of the users of this IP block to use
qdev_set_nic_properties() instead.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Reviewed-by: Peter Maydell 
Signed-off-by: Andrey Smirnov 
---
 hw/arm/fsl-imx6.c | 1 +
 hw/net/imx_fec.c  | 2 --
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index 26fd214004..2ed7146c52 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -385,6 +385,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 spi_table[i].irq));
 }
 
+qdev_set_nic_properties(DEVICE(&s->eth), &nd_table[0]);
 object_property_set_bool(OBJECT(&s->eth), true, "realized", &err);
 if (err) {
 error_propagate(errp, err);
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 90e6ee35ba..88b4b049d7 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1171,8 +1171,6 @@ static void imx_eth_realize(DeviceState *dev, Error 
**errp)
 
 qemu_macaddr_default_if_unset(&s->conf.macaddr);
 
-s->conf.peers.ncs[0] = nd_table[0].netdev;
-
 s->nic = qemu_new_nic(&imx_eth_net_info, &s->conf,
   object_get_typename(OBJECT(dev)),
   DEVICE(dev)->id, s);
-- 
2.13.5




[Qemu-devel] [PATCH v2 04/27] imx_fec: Use ENET_FTRL to determine truncation length

2017-10-23 Thread Andrey Smirnov
Frame truncation length, TRUNC_FL, is determined by the contents of
ENET_FTRL register, so convert the code to use it instead of a
hardcoded constant.

To avoid the case where TRUNC_FL is greater that ENET_MAX_FRAME_SIZE,
increase the value of the latter to its theoretical maximum of 16K.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 4 ++--
 include/hw/net/imx_fec.h | 3 ++-
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index eb034ffd0c..dda0816fb3 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1052,8 +1052,8 @@ static ssize_t imx_enet_receive(NetClientState *nc, const 
uint8_t *buf,
 crc_ptr = (uint8_t *) &crc;
 
 /* Huge frames are truncted.  */
-if (size > ENET_MAX_FRAME_SIZE) {
-size = ENET_MAX_FRAME_SIZE;
+if (size > s->regs[ENET_FTRL]) {
+size = s->regs[ENET_FTRL];
 flags |= ENET_BD_TR | ENET_BD_LG;
 }
 
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
index 4bc8f03ec2..0fcc4f0c71 100644
--- a/include/hw/net/imx_fec.h
+++ b/include/hw/net/imx_fec.h
@@ -86,7 +86,6 @@
 #define ENET_TCCR3 393
 #define ENET_MAX   400
 
-#define ENET_MAX_FRAME_SIZE2032
 
 /* EIR and EIMR */
 #define ENET_INT_HB(1 << 31)
@@ -155,6 +154,8 @@
 #define ENET_RCR_NLC   (1 << 30)
 #define ENET_RCR_GRS   (1 << 31)
 
+#define ENET_MAX_FRAME_SIZE(1 << ENET_RCR_MAX_FL_LENGTH)
+
 /* TCR */
 #define ENET_TCR_GTS   (1 << 0)
 #define ENET_TCR_FDEN  (1 << 2)
-- 
2.13.5




[Qemu-devel] [PATCH v2 03/27] imx_fec: Change queue flushing heuristics

2017-10-23 Thread Andrey Smirnov
In current implementation, packet queue flushing logic seem to suffer
from a deadlock like scenario if a packet is received by the interface
before before Rx ring is initialized by Guest's driver. Consider the
following sequence of events:

1. A QEMU instance is started against a TAP device on Linux
   host, running Linux guest, e. g., something to the effect
   of:

   qemu-system-arm \
  -net nic,model=imx.fec,netdev=lan0 \
  netdev tap,id=lan0,ifname=tap0,script=no,downscript=no \
  ... rest of the arguments ...

2. Once QEMU starts, but before guest reaches the point where
   FEC deriver is done initializing the HW, Guest, via TAP
   interface, receives a number of multicast MDNS packets from
   Host (not necessarily true for every OS, but it happens at
   least on Fedora 25)

3. Recieving a packet in such a state results in
   imx_eth_can_receive() returning '0', which in turn causes
   tap_send() to disable corresponding event (tap.c:203)

4. Once Guest's driver reaches the point where it is ready to
   recieve packets it prepares Rx ring descriptors and writes
   ENET_RDAR_RDAR to ENET_RDAR register to indicate to HW that
   more descriptors are ready. And at this points emulation
   layer does this:

 s->regs[index] = ENET_RDAR_RDAR;
 imx_eth_enable_rx(s);

   which, combined with:

  if (!s->regs[ENET_RDAR]) {
 qemu_flush_queued_packets(qemu_get_queue(s->nic));
  }

   results in Rx queue never being flushed and corresponding
   I/O event beign disabled.

To prevent the problem, change the code to always flush packet queue
when ENET_RDAR transitions 0 -> ENET_RDAR_RDAR.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 12 ++--
 include/hw/net/imx_fec.h |  1 +
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 8b2e4b8ffe..eb034ffd0c 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -533,7 +533,7 @@ static void imx_eth_do_tx(IMXFECState *s)
 }
 }
 
-static void imx_eth_enable_rx(IMXFECState *s)
+static void imx_eth_enable_rx(IMXFECState *s, bool flush)
 {
 IMXFECBufDesc bd;
 bool rx_ring_full;
@@ -544,7 +544,7 @@ static void imx_eth_enable_rx(IMXFECState *s)
 
 if (rx_ring_full) {
 FEC_PRINTF("RX buffer full\n");
-} else if (!s->regs[ENET_RDAR]) {
+} else if (flush) {
 qemu_flush_queued_packets(qemu_get_queue(s->nic));
 }
 
@@ -807,7 +807,7 @@ static void imx_eth_write(void *opaque, hwaddr offset, 
uint64_t value,
 if (s->regs[ENET_ECR] & ENET_ECR_ETHEREN) {
 if (!s->regs[index]) {
 s->regs[index] = ENET_RDAR_RDAR;
-imx_eth_enable_rx(s);
+imx_eth_enable_rx(s, true);
 }
 } else {
 s->regs[index] = 0;
@@ -930,7 +930,7 @@ static int imx_eth_can_receive(NetClientState *nc)
 
 FEC_PRINTF("\n");
 
-return s->regs[ENET_RDAR] ? 1 : 0;
+return !!s->regs[ENET_RDAR];
 }
 
 static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
@@ -1020,7 +1020,7 @@ static ssize_t imx_fec_receive(NetClientState *nc, const 
uint8_t *buf,
 }
 }
 s->rx_descriptor = addr;
-imx_eth_enable_rx(s);
+imx_eth_enable_rx(s, false);
 imx_eth_update(s);
 return len;
 }
@@ -1116,7 +1116,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const 
uint8_t *buf,
 }
 }
 s->rx_descriptor = addr;
-imx_eth_enable_rx(s);
+imx_eth_enable_rx(s, false);
 imx_eth_update(s);
 return len;
 }
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
index 62ad473b05..4bc8f03ec2 100644
--- a/include/hw/net/imx_fec.h
+++ b/include/hw/net/imx_fec.h
@@ -252,6 +252,7 @@ typedef struct IMXFECState {
 uint32_t phy_int_mask;
 
 bool is_fec;
+bool needs_flush;
 } IMXFECState;
 
 #endif
-- 
2.13.5




[Qemu-devel] [PATCH v2 06/27] imx_fec: Emulate SHIFT16 in ENETx_RACC

2017-10-23 Thread Andrey Smirnov
Needed to support latest Linux kernel driver which relies on that
functionality.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Reviewed-by: Peter Maydell 
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 23 +++
 include/hw/net/imx_fec.h |  2 ++
 2 files changed, 25 insertions(+)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 18de508e8c..131e7fd734 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1037,6 +1037,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const 
uint8_t *buf,
 uint8_t *crc_ptr;
 unsigned int buf_len;
 size_t size = len;
+bool shift16 = s->regs[ENET_RACC] & ENET_RACC_SHIFT16;
 
 FEC_PRINTF("len %d\n", (int)size);
 
@@ -1051,6 +1052,10 @@ static ssize_t imx_enet_receive(NetClientState *nc, 
const uint8_t *buf,
 crc = cpu_to_be32(crc32(~0, buf, size));
 crc_ptr = (uint8_t *) &crc;
 
+if (shift16) {
+size += 2;
+}
+
 /* Huge frames are truncted.  */
 if (size > s->regs[ENET_FTRL]) {
 size = s->regs[ENET_FTRL];
@@ -1087,6 +1092,24 @@ static ssize_t imx_enet_receive(NetClientState *nc, 
const uint8_t *buf,
 buf_len += size - 4;
 }
 buf_addr = bd.data;
+
+if (shift16) {
+/*
+ * If SHIFT16 bit of ENETx_RACC register is set we need to
+ * align the payload to 4-byte boundary.
+ */
+const uint8_t zeros[2] = { 0 };
+
+dma_memory_write(&address_space_memory, buf_addr,
+ zeros, sizeof(zeros));
+
+buf_addr += sizeof(zeros);
+buf_len  -= sizeof(zeros);
+
+/* We only do this once per Ethernet frame */
+shift16 = false;
+}
+
 dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
 buf += buf_len;
 if (size < 4) {
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
index 0fcc4f0c71..e482d1c13b 100644
--- a/include/hw/net/imx_fec.h
+++ b/include/hw/net/imx_fec.h
@@ -170,6 +170,8 @@
 #define ENET_TWFR_TFWR_LENGTH  (6)
 #define ENET_TWFR_STRFWD   (1 << 8)
 
+#define ENET_RACC_SHIFT16  BIT(7)
+
 /* Buffer Descriptor.  */
 typedef struct {
 uint16_t length;
-- 
2.13.5




[Qemu-devel] [PATCH v2 08/27] imx_fec: Use correct length for packet size

2017-10-23 Thread Andrey Smirnov
Use 'frame_size' instead of 'len' when calling qemu_send_packet(),
failing to do so results in malformed packets send in case when that
packed is fragmented into multiple DMA transactions.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Reviewed-by: Peter Maydell 
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 38d8c27dcd..eefb3b2c62 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -528,7 +528,7 @@ static void imx_enet_do_tx(IMXFECState *s, uint32_t index)
 }
 }
 /* Last buffer in frame.  */
-qemu_send_packet(qemu_get_queue(s->nic), frame, len);
+qemu_send_packet(qemu_get_queue(s->nic), frame, frame_size);
 ptr = frame;
 frame_size = 0;
 if (bd.option & ENET_BD_TX_INT) {
-- 
2.13.5




[Qemu-devel] [PATCH v2 09/27] imx_fec: Fix a typo in imx_enet_receive()

2017-10-23 Thread Andrey Smirnov
Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index eefb3b2c62..48d012cad6 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1121,7 +1121,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const 
uint8_t *buf,
 size += 2;
 }
 
-/* Huge frames are truncted.  */
+/* Huge frames are truncated. */
 if (size > s->regs[ENET_FTRL]) {
 size = s->regs[ENET_FTRL];
 flags |= ENET_BD_TR | ENET_BD_LG;
-- 
2.13.5




[Qemu-devel] [PATCH v2 05/27] imx_fec: Use MIN instead of explicit ternary operator

2017-10-23 Thread Andrey Smirnov
Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index dda0816fb3..18de508e8c 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1076,7 +1076,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const 
uint8_t *buf,
   TYPE_IMX_FEC, __func__);
 break;
 }
-buf_len = (size <= s->regs[ENET_MRBR]) ? size : s->regs[ENET_MRBR];
+buf_len = MIN(size, s->regs[ENET_MRBR]);
 bd.length = buf_len;
 size -= buf_len;
 
-- 
2.13.5




[Qemu-devel] [PATCH v2 07/27] imx_fec: Add support for multiple Tx DMA rings

2017-10-23 Thread Andrey Smirnov
More recent version of the IP block support more than one Tx DMA ring,
so add the code implementing that feature.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 106 ++-
 include/hw/net/imx_fec.h |  18 +++-
 2 files changed, 102 insertions(+), 22 deletions(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 131e7fd734..38d8c27dcd 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -198,13 +198,13 @@ static const char *imx_eth_reg_name(IMXFECState *s, 
uint32_t index)
 
 static const VMStateDescription vmstate_imx_eth = {
 .name = TYPE_IMX_FEC,
-.version_id = 2,
-.minimum_version_id = 2,
+.version_id = 3,
+.minimum_version_id = 3,
 .fields = (VMStateField[]) {
 VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX),
 VMSTATE_UINT32(rx_descriptor, IMXFECState),
-VMSTATE_UINT32(tx_descriptor, IMXFECState),
-
+VMSTATE_UINT32_ARRAY(tx_descriptor, IMXFECState, ENET_TX_RING_NUM),
+VMSTATE_UINT32(tx_ring_num, IMXFECState),
 VMSTATE_UINT32(phy_status, IMXFECState),
 VMSTATE_UINT32(phy_control, IMXFECState),
 VMSTATE_UINT32(phy_advertise, IMXFECState),
@@ -407,7 +407,7 @@ static void imx_fec_do_tx(IMXFECState *s)
 int frame_size = 0, descnt = 0;
 uint8_t frame[ENET_MAX_FRAME_SIZE];
 uint8_t *ptr = frame;
-uint32_t addr = s->tx_descriptor;
+uint32_t addr = s->tx_descriptor[0];
 
 while (descnt++ < IMX_MAX_DESC) {
 IMXFECBufDesc bd;
@@ -448,17 +448,47 @@ static void imx_fec_do_tx(IMXFECState *s)
 }
 }
 
-s->tx_descriptor = addr;
+s->tx_descriptor[0] = addr;
 
 imx_eth_update(s);
 }
 
-static void imx_enet_do_tx(IMXFECState *s)
+static void imx_enet_do_tx(IMXFECState *s, uint32_t index)
 {
 int frame_size = 0, descnt = 0;
 uint8_t frame[ENET_MAX_FRAME_SIZE];
 uint8_t *ptr = frame;
-uint32_t addr = s->tx_descriptor;
+uint32_t addr, int_txb, int_txf, tdsr;
+size_t ring;
+
+switch (index) {
+case ENET_TDAR:
+ring= 0;
+int_txb = ENET_INT_TXB;
+int_txf = ENET_INT_TXF;
+tdsr= ENET_TDSR;
+break;
+case ENET_TDAR1:
+ring= 1;
+int_txb = ENET_INT_TXB1;
+int_txf = ENET_INT_TXF1;
+tdsr= ENET_TDSR1;
+break;
+case ENET_TDAR2:
+ring= 2;
+int_txb = ENET_INT_TXB2;
+int_txf = ENET_INT_TXF2;
+tdsr= ENET_TDSR2;
+break;
+default:
+qemu_log_mask(LOG_GUEST_ERROR,
+  "%s: bogus value for index %x\n",
+  __func__, index);
+abort();
+break;
+}
+
+addr = s->tx_descriptor[ring];
 
 while (descnt++ < IMX_MAX_DESC) {
 IMXENETBufDesc bd;
@@ -502,32 +532,32 @@ static void imx_enet_do_tx(IMXFECState *s)
 ptr = frame;
 frame_size = 0;
 if (bd.option & ENET_BD_TX_INT) {
-s->regs[ENET_EIR] |= ENET_INT_TXF;
+s->regs[ENET_EIR] |= int_txf;
 }
 }
 if (bd.option & ENET_BD_TX_INT) {
-s->regs[ENET_EIR] |= ENET_INT_TXB;
+s->regs[ENET_EIR] |= int_txb;
 }
 bd.flags &= ~ENET_BD_R;
 /* Write back the modified descriptor.  */
 imx_enet_write_bd(&bd, addr);
 /* Advance to the next descriptor.  */
 if ((bd.flags & ENET_BD_W) != 0) {
-addr = s->regs[ENET_TDSR];
+addr = s->regs[tdsr];
 } else {
 addr += sizeof(bd);
 }
 }
 
-s->tx_descriptor = addr;
+s->tx_descriptor[ring] = addr;
 
 imx_eth_update(s);
 }
 
-static void imx_eth_do_tx(IMXFECState *s)
+static void imx_eth_do_tx(IMXFECState *s, uint32_t index)
 {
 if (!s->is_fec && (s->regs[ENET_ECR] & ENET_ECR_EN1588)) {
-imx_enet_do_tx(s);
+imx_enet_do_tx(s, index);
 } else {
 imx_fec_do_tx(s);
 }
@@ -585,7 +615,7 @@ static void imx_eth_reset(DeviceState *d)
 }
 
 s->rx_descriptor = 0;
-s->tx_descriptor = 0;
+memset(s->tx_descriptor, 0, sizeof(s->tx_descriptor));
 
 /* We also reset the PHY */
 phy_reset(s);
@@ -791,6 +821,7 @@ static void imx_eth_write(void *opaque, hwaddr offset, 
uint64_t value,
unsigned size)
 {
 IMXFECState *s = IMX_FEC(opaque);
+const bool single_tx_ring = s->tx_ring_num != 3;
 uint32_t index = offset >> 2;
 
 FEC_PRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx_eth_reg_name(s, index),
@@ -813,10 +844,18 @@ static void imx_eth_write(void *opaque, hwaddr offset, 
uint64_t value,
 s->regs[index] = 0;
 }
 

[Qemu-devel] [PATCH v2 10/27] imx_fec: Reserve full 4K page for the register file

2017-10-23 Thread Andrey Smirnov
Some i.MX SoCs (e.g. i.MX7) have FEC registers going as far as offset
0x614, so to avoid getting aborts when accessing those on QEMU, extend
the register file to cover 4KB of address space instead of just 1K.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/net/imx_fec.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index 48d012cad6..e236bc933c 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -1252,7 +1252,7 @@ static void imx_eth_realize(DeviceState *dev, Error 
**errp)
 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 
 memory_region_init_io(&s->iomem, OBJECT(dev), &imx_eth_ops, s,
-  TYPE_IMX_FEC, 0x400);
+  TYPE_IMX_FEC, 0x1000);
 sysbus_init_mmio(sbd, &s->iomem);
 sysbus_init_irq(sbd, &s->irq[0]);
 sysbus_init_irq(sbd, &s->irq[1]);
-- 
2.13.5




[Qemu-devel] [PATCH v2 12/27] sdhci: Implement write method of ACMD12ERRSTS register

2017-10-23 Thread Andrey Smirnov
Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/sd/sdhci.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index f561cc44e3..53e5e011a7 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1139,6 +1139,9 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, 
unsigned size)
 s->admasysaddr = (s->admasysaddr & (0xULL |
 ((uint64_t)mask << 32))) | ((uint64_t)value << 32);
 break;
+case SDHC_ACMD12ERRSTS:
+MASKED_WRITE(s->acmd12errsts, mask, value);
+break;
 case SDHC_FEAER:
 s->acmd12errsts |= value;
 s->errintsts |= (value >> 16) & s->errintstsen;
-- 
2.13.5




[Qemu-devel] [PATCH v2 13/27] i.MX: Add code to emulate i.MX7 CCM, PMU and ANALOG IP blocks

2017-10-23 Thread Andrey Smirnov
Add minimal code needed to allow upstream Linux guest to boot.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/misc/Makefile.objs  |   1 +
 hw/misc/imx7_ccm.c | 233 +
 include/hw/misc/imx7_ccm.h | 130 +
 3 files changed, 364 insertions(+)
 create mode 100644 hw/misc/imx7_ccm.c
 create mode 100644 include/hw/misc/imx7_ccm.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 29fb922cef..ac1be05a03 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -34,6 +34,7 @@ obj-$(CONFIG_IMX) += imx31_ccm.o
 obj-$(CONFIG_IMX) += imx25_ccm.o
 obj-$(CONFIG_IMX) += imx6_ccm.o
 obj-$(CONFIG_IMX) += imx6_src.o
+obj-$(CONFIG_IMX) += imx7_ccm.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/imx7_ccm.c b/hw/misc/imx7_ccm.c
new file mode 100644
index 00..2876164cfa
--- /dev/null
+++ b/hw/misc/imx7_ccm.c
@@ -0,0 +1,233 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 CCM, PMU and ANALOG IP blocks emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+
+#include "hw/misc/imx7_ccm.h"
+
+static uint32_t imx7_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
+{
+/*
+ * This function is "consumed" by GPT emulation code, however on
+ * i.MX7 each GPT block can have their own clock root. This means
+ * that this functions needs somehow to know requester's identity
+ * and the way to pass it: be it via additional IMXClk constants
+ * or by adding another argument to this method needs to be
+ * figured out
+ */
+qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Not implemented\n",
+  TYPE_IMX7_CCM, __func__);
+return 0;
+}
+
+static void imx7_ccm_reset(DeviceState *dev)
+{
+IMX7CCMState *s = IMX7_CCM(dev);
+
+s->analog[CCM_ANALOG_PLL_ARM] = 0x2042;
+s->analog[CCM_ANALOG_PLL_DDR] = 0x0060302c;
+s->analog[CCM_ANALOG_PLL_DDR_SS]  = 0x;
+s->analog[CCM_ANALOG_PLL_DDR_NUM] = 0x06aaac4d;
+s->analog[CCM_ANALOG_PLL_DDR_DENOM]   = 0x13ec;
+s->analog[CCM_ANALOG_PLL_480] = 0x2000;
+s->analog[CCM_ANALOG_PLL_480A]= 0x52605a56;
+s->analog[CCM_ANALOG_PLL_480B]= 0x52525216;
+s->analog[CCM_ANALOG_PLL_ENET]= 0x1fc0;
+s->analog[CCM_ANALOG_PLL_AUDIO]   = 0x0001301b;
+s->analog[CCM_ANALOG_PLL_AUDIO_SS]= 0x;
+s->analog[CCM_ANALOG_PLL_AUDIO_NUM]   = 0x05f5e100;
+s->analog[CCM_ANALOG_PLL_AUDIO_DENOM] = 0x2964619c;
+s->analog[CCM_ANALOG_PLL_VIDEO]   = 0x0008201b;
+s->analog[CCM_ANALOG_PLL_VIDEO_SS]= 0x;
+s->analog[CCM_ANALOG_PLL_VIDEO_NUM]   = 0xf699;
+s->analog[CCM_ANALOG_PLL_VIDEO_DENOM] = 0x000f4240;
+s->analog[CCM_ANALOG_PLL_MISC0]   = 0x;
+
+/* all PLLs need to be locked */
+s->analog[CCM_ANALOG_PLL_ARM]   |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_DDR]   |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_480]   |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_480A]  |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_480B]  |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_ENET]  |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_AUDIO] |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_VIDEO] |= CCM_ANALOG_PLL_LOCK;
+s->analog[CCM_ANALOG_PLL_MISC0] |= CCM_ANALOG_PLL_LOCK;
+
+/*
+ * Since I couldn't find any info about this in the reference
+ * manual the value of this register is based strictly on matching
+ * what Linux kernel expects it to be.
+ */
+s->analog[CCM_ANALOG_DIGPROG]  = 0x72;
+/*
+ * Set revision to be 1.0 (Arbitrary choice, no particular
+ * reason).
+ */
+s->analog[CCM_ANALOG_DIGPROG] |= 0x10;
+}
+
+#define CCM_INDEX(offset)   (((offset) & ~(hwaddr)0xF) / sizeof(uint32_t))
+#define CCM_BITOP(offset)   ((offset) & (hwaddr)0xF)
+
+enum {
+CCM_BITOP_NONE = 0x00,
+CCM_BITOP_SET  = 0x04,
+CCM_BITOP_CLR  = 0x08,
+CCM_BITOP_TOG  = 0x0C,
+};
+
+static uint64_t imx7_set_clr_tog_read(void *opaque, hwaddr offset,
+  unsigned size)
+{
+const uint32_t *mmio = opaque;
+
+return mmio[CCM_INDEX(offset)];
+}
+
+static void imx7_set_clr_tog_write(void *opaque, hwaddr offset,
+   uint64_t value, unsigned size)
+{
+const uint8_

[Qemu-devel] [PATCH v2 16/27] i.MX: Add code to emulate GPCv2 IP block

2017-10-23 Thread Andrey Smirnov
Add minimal code needed to allow upstream Linux guest to boot.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/intc/Makefile.objs   |   2 +-
 hw/intc/imx_gpcv2.c | 125 
 include/hw/intc/imx_gpcv2.h |  22 
 3 files changed, 148 insertions(+), 1 deletion(-)
 create mode 100644 hw/intc/imx_gpcv2.c
 create mode 100644 include/hw/intc/imx_gpcv2.h

diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
index 78426a7daf..db234901aa 100644
--- a/hw/intc/Makefile.objs
+++ b/hw/intc/Makefile.objs
@@ -4,7 +4,7 @@ common-obj-$(CONFIG_PL190) += pl190.o
 common-obj-$(CONFIG_PUV3) += puv3_intc.o
 common-obj-$(CONFIG_XILINX) += xilinx_intc.o
 common-obj-$(CONFIG_ETRAXFS) += etraxfs_pic.o
-common-obj-$(CONFIG_IMX) += imx_avic.o
+common-obj-$(CONFIG_IMX) += imx_avic.o imx_gpcv2.o
 common-obj-$(CONFIG_LM32) += lm32_pic.o
 common-obj-$(CONFIG_REALVIEW) += realview_gic.o
 common-obj-$(CONFIG_SLAVIO) += slavio_intctl.o
diff --git a/hw/intc/imx_gpcv2.c b/hw/intc/imx_gpcv2.c
new file mode 100644
index 00..496ed31b78
--- /dev/null
+++ b/hw/intc/imx_gpcv2.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 GPCv2 block emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/intc/imx_gpcv2.h"
+#include "qemu/log.h"
+
+#define GPC_PU_PGC_SW_PUP_REQ   0x0f8
+#define GPC_PU_PGC_SW_PDN_REQ   0x104
+
+#define USB_HSIC_PHY_SW_Pxx_REQ BIT(4)
+#define USB_OTG2_PHY_SW_Pxx_REQ BIT(3)
+#define USB_OTG1_PHY_SW_Pxx_REQ BIT(2)
+#define PCIE_PHY_SW_Pxx_REQ BIT(1)
+#define MIPI_PHY_SW_Pxx_REQ BIT(0)
+
+
+static void imx_gpcv2_reset(DeviceState *dev)
+{
+IMXGPCv2State *s = IMX_GPCV2(dev);
+
+memset(s->regs, 0, sizeof(s->regs));
+}
+
+static uint64_t imx_gpcv2_read(void *opaque, hwaddr offset,
+   unsigned size)
+{
+IMXGPCv2State *s = opaque;
+
+return s->regs[offset / sizeof(uint32_t)];
+}
+
+static void imx_gpcv2_write(void *opaque, hwaddr offset,
+uint64_t value, unsigned size)
+{
+IMXGPCv2State *s = opaque;
+const size_t idx = offset / sizeof(uint32_t);
+
+s->regs[idx] = value;
+
+/*
+ * Real HW will clear those bits once as a way to indicate that
+ * power up request is complete
+ */
+if (offset == GPC_PU_PGC_SW_PUP_REQ ||
+offset == GPC_PU_PGC_SW_PDN_REQ) {
+s->regs[idx] &= ~(USB_HSIC_PHY_SW_Pxx_REQ |
+  USB_OTG2_PHY_SW_Pxx_REQ |
+  USB_OTG1_PHY_SW_Pxx_REQ |
+  PCIE_PHY_SW_Pxx_REQ |
+  MIPI_PHY_SW_Pxx_REQ);
+}
+}
+
+static const struct MemoryRegionOps imx_gpcv2_ops = {
+.read = imx_gpcv2_read,
+.write = imx_gpcv2_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void imx_gpcv2_init(Object *obj)
+{
+SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+IMXGPCv2State *s = IMX_GPCV2(obj);
+
+memory_region_init_io(&s->iomem,
+  obj,
+  &imx_gpcv2_ops,
+  s,
+  TYPE_IMX_GPCV2 ".iomem",
+  sizeof(s->regs));
+sysbus_init_mmio(sd, &s->iomem);
+}
+
+static const VMStateDescription vmstate_imx_gpcv2 = {
+.name = TYPE_IMX_GPCV2,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(regs, IMXGPCv2State, GPC_NUM),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void imx_gpcv2_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->reset = imx_gpcv2_reset;
+dc->vmsd  = &vmstate_imx_gpcv2;
+dc->desc  = "i.MX GPCv2 Module";
+}
+
+static const TypeInfo imx_gpcv2_info = {
+.name  = TYPE_IMX_GPCV2,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(IMXGPCv2State),
+.instance_init = imx_gpcv2_init,
+.class_init= imx_gpcv2_class_init,
+};
+
+static void imx_gpcv2_register_type(void)
+{
+type_register_static(&imx_gpcv2_info);
+}
+type_init(imx_gpcv2_register_type)
diff --git a/include/hw/intc/imx_gpcv2.h b/includ

[Qemu-devel] [PATCH v2 14/27] i.MX: Add code to emulate i.MX2 watchdog IP block

2017-10-23 Thread Andrey Smirnov
Add enough code to emulate i.MX2 watchdog IP block so it would be
possible to reboot the machine running Linux Guest.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/misc/Makefile.objs  |  1 +
 hw/misc/imx2_wdt.c | 88 ++
 include/hw/misc/imx2_wdt.h | 34 ++
 3 files changed, 123 insertions(+)
 create mode 100644 hw/misc/imx2_wdt.c
 create mode 100644 include/hw/misc/imx2_wdt.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index ac1be05a03..c393a93456 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -35,6 +35,7 @@ obj-$(CONFIG_IMX) += imx25_ccm.o
 obj-$(CONFIG_IMX) += imx6_ccm.o
 obj-$(CONFIG_IMX) += imx6_src.o
 obj-$(CONFIG_IMX) += imx7_ccm.o
+obj-$(CONFIG_IMX) += imx2_wdt.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/imx2_wdt.c b/hw/misc/imx2_wdt.c
new file mode 100644
index 00..3a1c33aa51
--- /dev/null
+++ b/hw/misc/imx2_wdt.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX2 Watchdog IP block
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "sysemu/watchdog.h"
+
+#include "hw/misc/imx2_wdt.h"
+
+#define IMX2_WDT_WCR_WDABIT(5)  /* -> External Reset WDOG_B */
+#define IMX2_WDT_WCR_SRSBIT(4)  /* -> Software Reset Signal */
+
+static uint64_t imx2_wdt_read(void *opaque, hwaddr addr,
+  unsigned int size)
+{
+return 0;
+}
+
+static void imx2_wdt_write(void *opaque, hwaddr addr,
+   uint64_t value, unsigned int size)
+{
+if (addr == IMX2_WDT_WCR &&
+(value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))) {
+watchdog_perform_action();
+}
+}
+
+static const MemoryRegionOps imx2_wdt_ops = {
+.read  = imx2_wdt_read,
+.write = imx2_wdt_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the
+ * real device but in practice there is no reason for a guest
+ * to access this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void imx2_wdt_realize(DeviceState *dev, Error **errp)
+{
+IMX2WdtState *s = IMX2_WDT(dev);
+
+memory_region_init_io(&s->mmio, OBJECT(dev),
+  &imx2_wdt_ops, s,
+  TYPE_IMX2_WDT".mmio",
+  IMX2_WDT_REG_NUM * sizeof(uint16_t));
+sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
+}
+
+static void imx2_wdt_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->realize = imx2_wdt_realize;
+set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+}
+
+static const TypeInfo imx2_wdt_info = {
+.name  = TYPE_IMX2_WDT,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(IMX2WdtState),
+.class_init= imx2_wdt_class_init,
+};
+
+static WatchdogTimerModel model = {
+.wdt_name = "imx2-watchdog",
+.wdt_description = "i.MX2 Watchdog",
+};
+
+static void imx2_wdt_register_type(void)
+{
+watchdog_add_model(&model);
+type_register_static(&imx2_wdt_info);
+}
+type_init(imx2_wdt_register_type)
diff --git a/include/hw/misc/imx2_wdt.h b/include/hw/misc/imx2_wdt.h
new file mode 100644
index 00..e67ac6939d
--- /dev/null
+++ b/include/hw/misc/imx2_wdt.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX2 Watchdog IP block
+ *
+ * Author: Andrey Smirnov 
+ *
+ * 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 IMX2_WDT_H
+#define IMX2_WDT_H
+
+#include "qemu/bitops.h"
+#include "hw/sysbus.h"
+
+#define TYPE_IMX2_WDT "imx2.wdt"
+#define IMX2_WDT(obj) OBJECT_CHECK(IMX2WdtState, (obj), TYPE_IMX2_WDT)
+
+enum IMX2WdtRegisters {
+IMX2_WDT_WCR = 0x,
+IMX2_WDT_REG_NUM = 0x0008 / sizeof(uint16_t) + 1,
+};
+
+
+typedef struct IMX2WdtState {
+/*  */
+SysBusDevice parent_obj;
+
+MemoryRegion mmio;
+} IMX2WdtState;
+
+#endif /* IMX7_SNVS_H */
-- 
2.13.5




[Qemu-devel] [PATCH v2 11/27] sdhci: Add i.MX specific subtype of SDHCI

2017-10-23 Thread Andrey Smirnov
IP block found on several generations of i.MX family does not use
vanilla SDHCI implementation and it comes with a number of quirks.

Introduce i.MX SDHCI subtype of SDHCI block to add code necessary to
support unmodified Linux guest driver.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/sd/sdhci-internal.h |  15 ++
 hw/sd/sdhci.c  | 127 -
 include/hw/sd/sdhci.h  |   8 
 3 files changed, 148 insertions(+), 2 deletions(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index 161177cf39..2a1b4b06ee 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -91,6 +91,8 @@
 #define SDHC_CTRL_ADMA2_32 0x10
 #define SDHC_CTRL_ADMA2_64 0x18
 #define SDHC_DMA_TYPE(x)   ((x) & SDHC_CTRL_DMA_CHECK_MASK)
+#define SDHC_CTRL_4BITBUS  0x02
+#define SDHC_CTRL_8BITBUS  0x20
 
 /* R/W Power Control Register 0x0 */
 #define SDHC_PWRCON0x29
@@ -229,4 +231,17 @@ enum {
 
 extern const VMStateDescription sdhci_vmstate;
 
+
+#define ESDHC_MIX_CTRL  0x48
+#define ESDHC_VENDOR_SPEC   0xc0
+#define ESDHC_DLL_CTRL  0x60
+
+#define ESDHC_TUNING_CTRL   0xcc
+#define ESDHC_TUNE_CTRL_STATUS  0x68
+#define ESDHC_WTMK_LVL  0x44
+
+#define ESDHC_CTRL_4BITBUS  (0x1 << 1)
+#define ESDHC_CTRL_8BITBUS  (0x2 << 1)
+
+
 #endif
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index 6d6a791ee9..f561cc44e3 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -265,7 +265,8 @@ static void sdhci_send_command(SDHCIState *s)
 }
 }
 
-if ((s->norintstsen & SDHC_NISEN_TRSCMP) &&
+if (!(s->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) &&
+(s->norintstsen & SDHC_NISEN_TRSCMP) &&
 (s->cmdreg & SDHC_CMD_RESPONSE) == SDHC_CMD_RSP_WITH_BUSY) {
 s->norintsts |= SDHC_NIS_TRSCMP;
 }
@@ -1191,6 +1192,8 @@ static void sdhci_initfn(SDHCIState *s)
 
 s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 
sdhci_raise_insertion_irq, s);
 s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, 
s);
+
+s->io_ops = &sdhci_mmio_ops;
 }
 
 static void sdhci_uninitfn(SDHCIState *s)
@@ -1347,7 +1350,7 @@ static void sdhci_sysbus_realize(DeviceState *dev, Error 
** errp)
 s->buf_maxsz = sdhci_get_fifolen(s);
 s->fifo_buffer = g_malloc0(s->buf_maxsz);
 sysbus_init_irq(sbd, &s->irq);
-memory_region_init_io(&s->iomem, OBJECT(s), &sdhci_mmio_ops, s, "sdhci",
+memory_region_init_io(&s->iomem, OBJECT(s), s->io_ops, s, "sdhci",
 SDHC_REGISTERS_MAP_SIZE);
 sysbus_init_mmio(sbd, &s->iomem);
 }
@@ -1386,11 +1389,131 @@ static const TypeInfo sdhci_bus_info = {
 .class_init = sdhci_bus_class_init,
 };
 
+static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
+{
+SDHCIState *s = SYSBUS_SDHCI(opaque);
+uint32_t ret;
+uint16_t hostctl;
+
+switch (offset) {
+default:
+return sdhci_read(opaque, offset, size);
+
+case SDHC_HOSTCTL:
+hostctl = SDHC_DMA_TYPE(s->hostctl) << 5;
+
+if (s->hostctl & SDHC_CTRL_8BITBUS) {
+hostctl |= ESDHC_CTRL_8BITBUS;
+}
+
+if (s->hostctl & SDHC_CTRL_4BITBUS) {
+hostctl |= ESDHC_CTRL_4BITBUS;
+}
+
+ret = hostctl | (s->blkgap << 16) |
+(s->wakcon << 24);
+
+break;
+
+case ESDHC_DLL_CTRL:
+case ESDHC_TUNE_CTRL_STATUS:
+case 0x6c:
+case ESDHC_TUNING_CTRL:
+case ESDHC_VENDOR_SPEC:
+case ESDHC_MIX_CTRL:
+case ESDHC_WTMK_LVL:
+ret = 0;
+break;
+}
+
+return ret;
+}
+
+static void
+usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
+{
+SDHCIState *s = SYSBUS_SDHCI(opaque);
+uint8_t hostctl = 0;
+uint32_t value = (uint32_t)val;
+
+switch (offset) {
+case ESDHC_DLL_CTRL:
+case ESDHC_TUNE_CTRL_STATUS:
+case 0x6c:
+case ESDHC_TUNING_CTRL:
+case ESDHC_WTMK_LVL:
+case ESDHC_VENDOR_SPEC:
+break;
+
+case SDHC_HOSTCTL:
+if (value & ESDHC_CTRL_8BITBUS) {
+hostctl |= SDHC_CTRL_8BITBUS;
+}
+
+if (value & ESDHC_CTRL_4BITBUS) {
+hostctl |= ESDHC_CTRL_4BITBUS;
+}
+
+hostctl |= SDHC_DMA_TYPE(value >> 5);
+
+value &= ~0xFE;
+value |= hostctl;
+value &= ~0xFF00;
+value |= s->pwrcon;
+
+sdhci_write(opaque, offset, value, size);
+break;
+
+case ESDHC_MIX_CTRL:
+/*
+ * The layout o

[Qemu-devel] [PATCH v2 19/27] i.MX: Add code to emulate SDMA IP block

2017-10-23 Thread Andrey Smirnov
Add minimal code needed to allow upstream Linux guest to boot.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/dma/Makefile.objs  |  1 +
 hw/dma/imx_sdma.c | 99 +++
 include/hw/dma/imx_sdma.h | 22 +++
 3 files changed, 122 insertions(+)
 create mode 100644 hw/dma/imx_sdma.c
 create mode 100644 include/hw/dma/imx_sdma.h

diff --git a/hw/dma/Makefile.objs b/hw/dma/Makefile.objs
index 087c8e6855..3cee0b1047 100644
--- a/hw/dma/Makefile.objs
+++ b/hw/dma/Makefile.objs
@@ -14,3 +14,4 @@ obj-$(CONFIG_XLNX_ZYNQMP) += xlnx_dpdma.o
 obj-$(CONFIG_OMAP) += omap_dma.o soc_dma.o
 obj-$(CONFIG_PXA2XX) += pxa2xx_dma.o
 obj-$(CONFIG_RASPI) += bcm2835_dma.o
+obj-$(CONFIG_IMX) += imx_sdma.o
diff --git a/hw/dma/imx_sdma.c b/hw/dma/imx_sdma.c
new file mode 100644
index 00..0776e41b9a
--- /dev/null
+++ b/hw/dma/imx_sdma.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 IOMUXC block emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/dma/imx_sdma.h"
+#include "qemu/log.h"
+
+static void imx_sdma_reset(DeviceState *dev)
+{
+IMXSDMAState *s = IMX_SDMA(dev);
+
+memset(s->regs, 0, sizeof(s->regs));
+}
+
+static uint64_t imx_sdma_read(void *opaque, hwaddr offset,
+   unsigned size)
+{
+IMXSDMAState *s = opaque;
+return s->regs[offset / sizeof(uint32_t)];
+}
+
+static void imx_sdma_write(void *opaque, hwaddr offset,
+uint64_t value, unsigned size)
+{
+IMXSDMAState *s = opaque;
+s->regs[offset / sizeof(uint32_t)] = value;
+}
+
+static const struct MemoryRegionOps imx_sdma_ops = {
+.read = imx_sdma_read,
+.write = imx_sdma_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void imx_sdma_init(Object *obj)
+{
+SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+IMXSDMAState *s = IMX_SDMA(obj);
+
+memory_region_init_io(&s->iomem,
+  obj,
+  &imx_sdma_ops,
+  s,
+  TYPE_IMX_SDMA ".iomem",
+  sizeof(s->regs));
+sysbus_init_mmio(sd, &s->iomem);
+}
+
+static const VMStateDescription vmstate_imx_sdma = {
+.name = TYPE_IMX_SDMA,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(regs, IMXSDMAState, SDMA_NUM),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void imx_sdma_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->reset = imx_sdma_reset;
+dc->vmsd  = &vmstate_imx_sdma;
+dc->desc  = "i.MX IOMUXC Module";
+}
+
+static const TypeInfo imx_sdma_info = {
+.name  = TYPE_IMX_SDMA,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(IMXSDMAState),
+.instance_init = imx_sdma_init,
+.class_init= imx_sdma_class_init,
+};
+
+static void imx_sdma_register_type(void)
+{
+type_register_static(&imx_sdma_info);
+}
+type_init(imx_sdma_register_type)
diff --git a/include/hw/dma/imx_sdma.h b/include/hw/dma/imx_sdma.h
new file mode 100644
index 00..13c5be7a00
--- /dev/null
+++ b/include/hw/dma/imx_sdma.h
@@ -0,0 +1,22 @@
+#ifndef IMX_SDMA_H
+#define IMX_SDMA_H
+
+#include "hw/sysbus.h"
+
+enum IMXSDMARegisters {
+SDMA_NUM = 0x300 / sizeof(uint32_t) + 1,
+};
+
+typedef struct IMXSDMAState {
+/*< private >*/
+SysBusDevice parent_obj;
+
+/*< public >*/
+MemoryRegion iomem;
+uint32_t regs[SDMA_NUM];
+} IMXSDMAState;
+
+#define TYPE_IMX_SDMA "imx-sdma"
+#define IMX_SDMA(obj) OBJECT_CHECK(IMXSDMAState, (obj), TYPE_IMX_SDMA)
+
+#endif /* IMX_SDMA_H */
-- 
2.13.5




[Qemu-devel] [PATCH v2 20/27] i.MX: Add code to emulate FlexCAN IP block

2017-10-23 Thread Andrey Smirnov
Add minimal code needed to allow upstream Linux guest to boot.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/misc/Makefile.objs |  1 +
 hw/misc/imx_flexcan.c | 99 +++
 include/hw/misc/imx_flexcan.h | 22 ++
 3 files changed, 122 insertions(+)
 create mode 100644 hw/misc/imx_flexcan.c
 create mode 100644 include/hw/misc/imx_flexcan.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 492c535330..943b22af40 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -38,6 +38,7 @@ obj-$(CONFIG_IMX) += imx7_ccm.o
 obj-$(CONFIG_IMX) += imx2_wdt.o
 obj-$(CONFIG_IMX) += imx7_snvs.o
 obj-$(CONFIG_IMX) += imx7_iomuxc.o
+obj-$(CONFIG_IMX) += imx_flexcan.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/imx_flexcan.c b/hw/misc/imx_flexcan.c
new file mode 100644
index 00..dd4d3d6dc1
--- /dev/null
+++ b/hw/misc/imx_flexcan.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX FlexCAN block emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/misc/imx_flexcan.h"
+#include "qemu/log.h"
+
+static void imx_flexcan_reset(DeviceState *dev)
+{
+IMXFlexCANState *s = IMX_FLEXCAN(dev);
+
+memset(s->regs, 0, sizeof(s->regs));
+}
+
+static uint64_t imx_flexcan_read(void *opaque, hwaddr offset,
+   unsigned size)
+{
+IMXFlexCANState *s = opaque;
+return s->regs[offset / sizeof(uint32_t)];
+}
+
+static void imx_flexcan_write(void *opaque, hwaddr offset,
+uint64_t value, unsigned size)
+{
+IMXFlexCANState *s = opaque;
+s->regs[offset / sizeof(uint32_t)] = value;
+}
+
+static const struct MemoryRegionOps imx_flexcan_ops = {
+.read = imx_flexcan_read,
+.write = imx_flexcan_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void imx_flexcan_init(Object *obj)
+{
+SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+IMXFlexCANState *s = IMX_FLEXCAN(obj);
+
+memory_region_init_io(&s->iomem,
+  obj,
+  &imx_flexcan_ops,
+  s,
+  TYPE_IMX_FLEXCAN ".iomem",
+  sizeof(s->regs));
+sysbus_init_mmio(sd, &s->iomem);
+}
+
+static const VMStateDescription vmstate_imx_flexcan = {
+.name = TYPE_IMX_FLEXCAN,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(regs, IMXFlexCANState, FLEXCAN_NUM),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void imx_flexcan_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->reset = imx_flexcan_reset;
+dc->vmsd  = &vmstate_imx_flexcan;
+dc->desc  = "i.MX FlexCAN Module";
+}
+
+static const TypeInfo imx_flexcan_info = {
+.name  = TYPE_IMX_FLEXCAN,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(IMXFlexCANState),
+.instance_init = imx_flexcan_init,
+.class_init= imx_flexcan_class_init,
+};
+
+static void imx_flexcan_register_type(void)
+{
+type_register_static(&imx_flexcan_info);
+}
+type_init(imx_flexcan_register_type)
diff --git a/include/hw/misc/imx_flexcan.h b/include/hw/misc/imx_flexcan.h
new file mode 100644
index 00..da9980cf86
--- /dev/null
+++ b/include/hw/misc/imx_flexcan.h
@@ -0,0 +1,22 @@
+#ifndef IMX_FLEXCAN_H
+#define IMX_FLEXCAN_H
+
+#include "hw/sysbus.h"
+
+enum IMXFlexCANRegisters {
+FLEXCAN_NUM = 0x9E0 / sizeof(uint32_t) + 1,
+};
+
+typedef struct IMXFlexCANState {
+/*< private >*/
+SysBusDevice parent_obj;
+
+/*< public >*/
+MemoryRegion iomem;
+uint32_t regs[FLEXCAN_NUM];
+} IMXFlexCANState;
+
+#define TYPE_IMX_FLEXCAN "imx-flexcan"
+#define IMX_FLEXCAN(obj) OBJECT_CHECK(IMXFlexCANState, (obj), TYPE_IMX_FLEXCAN)
+
+#endif /* IMX_FLEXCAN_H */
-- 
2.13.5




[Qemu-devel] [PATCH v2 15/27] i.MX: Add code to emulate i.MX7 SNVS IP-block

2017-10-23 Thread Andrey Smirnov
Add code to emulate SNVS IP-block. Currently only the bits needed to
be able to emulate machine shutdown are implemented.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/misc/Makefile.objs   |  1 +
 hw/misc/imx7_snvs.c | 83 +
 include/hw/misc/imx7_snvs.h | 35 +++
 3 files changed, 119 insertions(+)
 create mode 100644 hw/misc/imx7_snvs.c
 create mode 100644 include/hw/misc/imx7_snvs.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index c393a93456..16cee88e0f 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -36,6 +36,7 @@ obj-$(CONFIG_IMX) += imx6_ccm.o
 obj-$(CONFIG_IMX) += imx6_src.o
 obj-$(CONFIG_IMX) += imx7_ccm.o
 obj-$(CONFIG_IMX) += imx2_wdt.o
+obj-$(CONFIG_IMX) += imx7_snvs.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/imx7_snvs.c b/hw/misc/imx7_snvs.c
new file mode 100644
index 00..670b9f4639
--- /dev/null
+++ b/hw/misc/imx7_snvs.c
@@ -0,0 +1,83 @@
+/*
+ * IMX7 Secure Non-Volatile Storage
+ *
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * Bare minimum emulation code needed to support being able to shut
+ * down linux guest gracefully.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/misc/imx7_snvs.h"
+#include "qemu/log.h"
+#include "sysemu/sysemu.h"
+
+static uint64_t imx7_snvs_read(void *opaque, hwaddr offset, unsigned size)
+{
+return 0;
+}
+
+static void imx7_snvs_write(void *opaque, hwaddr offset,
+uint64_t v, unsigned size)
+{
+const uint32_t value = v;
+const uint32_t mask  = SNVS_LPCR_TOP | SNVS_LPCR_DP_EN;
+
+if (offset == SNVS_LPCR && ((value & mask) == mask)) {
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+}
+}
+
+static const struct MemoryRegionOps imx7_snvs_ops = {
+.read = imx7_snvs_read,
+.write = imx7_snvs_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void imx7_snvs_init(Object *obj)
+{
+SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+IMX7SNVSState *s = IMX7_SNVS(obj);
+
+memory_region_init_io(&s->mmio, obj, &imx7_snvs_ops, s,
+  TYPE_IMX7_SNVS, 0x1000);
+
+sysbus_init_mmio(sd, &s->mmio);
+}
+
+static void imx7_snvs_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->desc  = "i.MX7 Secure Non-Volatile Storage Module";
+}
+
+static const TypeInfo imx7_snvs_info = {
+.name  = TYPE_IMX7_SNVS,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(IMX7SNVSState),
+.instance_init = imx7_snvs_init,
+.class_init= imx7_snvs_class_init,
+};
+
+static void imx7_snvs_register_type(void)
+{
+type_register_static(&imx7_snvs_info);
+}
+type_init(imx7_snvs_register_type)
diff --git a/include/hw/misc/imx7_snvs.h b/include/hw/misc/imx7_snvs.h
new file mode 100644
index 00..255f8f26f9
--- /dev/null
+++ b/include/hw/misc/imx7_snvs.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 SNVS block emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * 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 IMX7_SNVS_H
+#define IMX7_SNVS_H
+
+#include "qemu/bitops.h"
+#include "hw/sysbus.h"
+
+
+enum IMX7SNVSRegisters {
+SNVS_LPCR = 0x38,
+SNVS_LPCR_TOP   = BIT(6),
+SNVS_LPCR_DP_EN = BIT(5)
+};
+
+#define TYPE_IMX7_SNVS "imx7.snvs"
+#define IMX7_SNVS(obj) OBJECT_CHECK(IMX7SNVSState, (obj), TYPE_IMX7_SNVS)
+
+typedef struct IMX7SNVSState {
+/*  */
+SysBusDevice parent_obj;
+
+MemoryRegion mmio;
+} IMX7SNVSState;
+
+#endif /* IMX7_SNVS_H */
-- 
2.13.5




[Qemu-devel] [PATCH v2 17/27] i.MX: Add code to emulate i.MX7 IOMUXC IP block

2017-10-23 Thread Andrey Smirnov
Add minimal code needed to allow upstream Linux guest to boot.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/misc/Makefile.objs |  1 +
 hw/misc/imx7_iomuxc.c | 99 +++
 include/hw/misc/imx7_iomuxc.h | 22 ++
 3 files changed, 122 insertions(+)
 create mode 100644 hw/misc/imx7_iomuxc.c
 create mode 100644 include/hw/misc/imx7_iomuxc.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 16cee88e0f..492c535330 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -37,6 +37,7 @@ obj-$(CONFIG_IMX) += imx6_src.o
 obj-$(CONFIG_IMX) += imx7_ccm.o
 obj-$(CONFIG_IMX) += imx2_wdt.o
 obj-$(CONFIG_IMX) += imx7_snvs.o
+obj-$(CONFIG_IMX) += imx7_iomuxc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/imx7_iomuxc.c b/hw/misc/imx7_iomuxc.c
new file mode 100644
index 00..aa26a7485f
--- /dev/null
+++ b/hw/misc/imx7_iomuxc.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 IOMUXC block emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/misc/imx7_iomuxc.h"
+#include "qemu/log.h"
+
+static void imx7_iomuxc_reset(DeviceState *dev)
+{
+IMX7IOMUXCState *s = IMX7_IOMUXC(dev);
+
+memset(s->regs, 0, sizeof(s->regs));
+}
+
+static uint64_t imx7_iomuxc_read(void *opaque, hwaddr offset,
+   unsigned size)
+{
+IMX7IOMUXCState *s = opaque;
+return s->regs[offset / sizeof(uint32_t)];
+}
+
+static void imx7_iomuxc_write(void *opaque, hwaddr offset,
+uint64_t value, unsigned size)
+{
+IMX7IOMUXCState *s = opaque;
+s->regs[offset / sizeof(uint32_t)] = value;
+}
+
+static const struct MemoryRegionOps imx7_iomuxc_ops = {
+.read = imx7_iomuxc_read,
+.write = imx7_iomuxc_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void imx7_iomuxc_init(Object *obj)
+{
+SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+IMX7IOMUXCState *s = IMX7_IOMUXC(obj);
+
+memory_region_init_io(&s->iomem,
+  obj,
+  &imx7_iomuxc_ops,
+  s,
+  TYPE_IMX7_IOMUXC ".iomem",
+  sizeof(s->regs));
+sysbus_init_mmio(sd, &s->iomem);
+}
+
+static const VMStateDescription vmstate_imx7_iomuxc = {
+.name = TYPE_IMX7_IOMUXC,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(regs, IMX7IOMUXCState, IOMUXC_NUM),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void imx7_iomuxc_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->reset = imx7_iomuxc_reset;
+dc->vmsd  = &vmstate_imx7_iomuxc;
+dc->desc  = "i.MX IOMUXC Module";
+}
+
+static const TypeInfo imx7_iomuxc_info = {
+.name  = TYPE_IMX7_IOMUXC,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(IMX7IOMUXCState),
+.instance_init = imx7_iomuxc_init,
+.class_init= imx7_iomuxc_class_init,
+};
+
+static void imx7_iomuxc_register_type(void)
+{
+type_register_static(&imx7_iomuxc_info);
+}
+type_init(imx7_iomuxc_register_type)
diff --git a/include/hw/misc/imx7_iomuxc.h b/include/hw/misc/imx7_iomuxc.h
new file mode 100644
index 00..7041a1ff42
--- /dev/null
+++ b/include/hw/misc/imx7_iomuxc.h
@@ -0,0 +1,22 @@
+#ifndef IMX7_IOMUXC_H
+#define IMX7_IOMUXC_H
+
+#include "hw/sysbus.h"
+
+enum IMX7IOMUXCRegisters {
+IOMUXC_NUM = 0x740 / sizeof(uint32_t),
+};
+
+typedef struct IMX7IOMUXCState {
+/*< private >*/
+SysBusDevice parent_obj;
+
+/*< public >*/
+MemoryRegion iomem;
+uint32_t regs[IOMUXC_NUM];
+} IMX7IOMUXCState;
+
+#define TYPE_IMX7_IOMUXC "imx7-iomuxc"
+#define IMX7_IOMUXC(obj) OBJECT_CHECK(IMX7IOMUXCState, (obj), TYPE_IMX7_IOMUXC)
+
+#endif /* IMX7_IOMUXC_H */
-- 
2.13.5




[Qemu-devel] [PATCH v2 26/27] i.MX: Add i.MX7 SOC implementation.

2017-10-23 Thread Andrey Smirnov
The following interfaces are partially or fully emulated:

* up to 2 Cortex A9 cores (SMP works with PSCI)
* A7 MPCORE (identical to A15 MPCORE)
* 4 GPTs modules
* 7 GPIO controllers
* 2 IOMUXC controllers
* 1 CCM module
* 1 SVNS module
* 1 SRC module
* 1 GPCv2 controller
* 4 eCSPI controllers
* 4 I2C controllers
* 7 i.MX UART controllers
* 2 FlexCAN controllers
* 2 Ethernet controllers (FEC)
* 3 SD controllers (USDHC)
* 4 WDT modules
* 1 SDMA module
* 1 GPR module
* 2 USBMISC modules
* 2 ADC modules
* 1 PCIe controller

Tested to boot and work with upstream Linux (4.13+) guest.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 default-configs/arm-softmmu.mak |   1 +
 hw/arm/Makefile.objs|   2 +
 hw/arm/fsl-imx7.c   | 596 
 include/hw/arm/fsl-imx7.h   | 217 +++
 4 files changed, 816 insertions(+)
 create mode 100644 hw/arm/fsl-imx7.c
 create mode 100644 include/hw/arm/fsl-imx7.h

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 225ebbd90a..a2f318d6dd 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -118,6 +118,7 @@ CONFIG_ALLWINNER_A10=y
 CONFIG_FSL_IMX6=y
 CONFIG_FSL_IMX31=y
 CONFIG_FSL_IMX25=y
+CONFIG_FSL_IMX7=y
 
 CONFIG_IMX_I2C=y
 
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index a2e56ecaae..33f6051ae3 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -19,3 +19,5 @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
 obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
 obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
 obj-$(CONFIG_MPS2) += mps2.o
+obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o
+
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
new file mode 100644
index 00..f1a6a79179
--- /dev/null
+++ b/hw/arm/fsl-imx7.c
@@ -0,0 +1,596 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 SoC definitions
+ *
+ * Author: Andrey Smirnov 
+ *
+ * Based on hw/arm/fsl-imx6.c
+ *
+ * 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.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/fsl-imx7.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+
+#define NAME_SIZE 20
+
+static void fsl_imx7_init(Object *obj)
+{
+BusState *sysbus = sysbus_get_default();
+FslIMX7State *s = FSL_IMX7(obj);
+char name[NAME_SIZE];
+int i;
+
+if (smp_cpus > FSL_IMX7_NUM_CPUS) {
+error_report("%s: Only %d CPUs are supported (%d requested)",
+ TYPE_FSL_IMX7, FSL_IMX7_NUM_CPUS, smp_cpus);
+exit(1);
+}
+
+for (i = 0; i < smp_cpus; i++) {
+object_initialize(&s->cpu[i], sizeof(s->cpu[i]),
+  "cortex-a7-" TYPE_ARM_CPU);
+snprintf(name, NAME_SIZE, "cpu%d", i);
+object_property_add_child(obj, name, OBJECT(&s->cpu[i]),
+  &error_fatal);
+}
+
+/*
+ * A7MPCORE
+ */
+object_initialize(&s->a7mpcore, sizeof(s->a7mpcore), TYPE_A15MPCORE_PRIV);
+qdev_set_parent_bus(DEVICE(&s->a7mpcore), sysbus);
+object_property_add_child(obj, "a7mpcore",
+  OBJECT(&s->a7mpcore), &error_fatal);
+
+/*
+ * GPIOs 1 to 7
+ */
+for (i = 0; i < FSL_IMX7_NUM_GPIOS; i++) {
+object_initialize(&s->gpio[i], sizeof(s->gpio[i]),
+  TYPE_IMX_GPIO);
+qdev_set_parent_bus(DEVICE(&s->gpio[i]), sysbus);
+snprintf(name, NAME_SIZE, "gpio%d", i);
+object_property_add_child(obj, name,
+  OBJECT(&s->gpio[i]), &error_fatal);
+}
+
+/*
+ * IOMUXC and IOMUXC_LPSR
+ */
+for (i = 0; i < FSL_IMX7_NUM_IOMUXCS; i++) {
+object_initialize(&s->iomuxc[i], sizeof(s->iomuxc[i]),
+  TYPE_IMX7_IOMUXC);
+qdev_set_parent_bus(DEVICE(&s->iomuxc[i]), sysbus);
+snprintf(name, NAME_SIZE, "iomuxc%d", i);
+object_property_add_child(obj, name,
+  OBJECT(&s->iomuxc[i]), &error_fatal);
+}

[Qemu-devel] [PATCH v2 23/27] i.MX: Add code to emulate i.MX7 USBMISC IP block

2017-10-23 Thread Andrey Smirnov
Add minimal code needed to allow upstream Linux guest to boot.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/usb/Makefile.objs |  1 +
 hw/usb/imx-usbmisc.c | 99 
 include/hw/usb/imx-usbmisc.h | 22 ++
 3 files changed, 122 insertions(+)
 create mode 100644 hw/usb/imx-usbmisc.c
 create mode 100644 include/hw/usb/imx-usbmisc.h

diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
index 97f1c4561a..813359fadc 100644
--- a/hw/usb/Makefile.objs
+++ b/hw/usb/Makefile.objs
@@ -12,6 +12,7 @@ common-obj-$(CONFIG_USB_XHCI_NEC) += hcd-xhci-nec.o
 common-obj-$(CONFIG_USB_MUSB) += hcd-musb.o
 
 obj-$(CONFIG_TUSB6010) += tusb6010.o
+obj-$(CONFIG_IMX)  += imx-usbmisc.o
 
 # emulated usb devices
 common-obj-$(CONFIG_USB) += dev-hub.o
diff --git a/hw/usb/imx-usbmisc.c b/hw/usb/imx-usbmisc.c
new file mode 100644
index 00..d5e236a4be
--- /dev/null
+++ b/hw/usb/imx-usbmisc.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 IOMUXC block emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/usb/imx-usbmisc.h"
+#include "qemu/log.h"
+
+static void imx_usbmisc_reset(DeviceState *dev)
+{
+IMXUSBMiscState *s = IMX_USBMISC(dev);
+
+memset(s->regs, 0, sizeof(s->regs));
+}
+
+static uint64_t imx_usbmisc_read(void *opaque, hwaddr offset,
+   unsigned size)
+{
+IMXUSBMiscState *s = opaque;
+return s->regs[offset / sizeof(uint32_t)];
+}
+
+static void imx_usbmisc_write(void *opaque, hwaddr offset,
+uint64_t value, unsigned size)
+{
+IMXUSBMiscState *s = opaque;
+s->regs[offset / sizeof(uint32_t)] = value;
+}
+
+static const struct MemoryRegionOps imx_usbmisc_ops = {
+.read = imx_usbmisc_read,
+.write = imx_usbmisc_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void imx_usbmisc_init(Object *obj)
+{
+SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+IMXUSBMiscState *s = IMX_USBMISC(obj);
+
+memory_region_init_io(&s->iomem,
+  obj,
+  &imx_usbmisc_ops,
+  s,
+  TYPE_IMX_USBMISC ".iomem",
+  sizeof(s->regs));
+sysbus_init_mmio(sd, &s->iomem);
+}
+
+static const VMStateDescription vmstate_imx_usbmisc = {
+.name = TYPE_IMX_USBMISC,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(regs, IMXUSBMiscState, USBMISC_NUM),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void imx_usbmisc_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->reset = imx_usbmisc_reset;
+dc->vmsd  = &vmstate_imx_usbmisc;
+dc->desc  = "i.MX IOMUXC Module";
+}
+
+static const TypeInfo imx_usbmisc_info = {
+.name  = TYPE_IMX_USBMISC,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(IMXUSBMiscState),
+.instance_init = imx_usbmisc_init,
+.class_init= imx_usbmisc_class_init,
+};
+
+static void imx_usbmisc_register_type(void)
+{
+type_register_static(&imx_usbmisc_info);
+}
+type_init(imx_usbmisc_register_type)
diff --git a/include/hw/usb/imx-usbmisc.h b/include/hw/usb/imx-usbmisc.h
new file mode 100644
index 00..64b06f3d3c
--- /dev/null
+++ b/include/hw/usb/imx-usbmisc.h
@@ -0,0 +1,22 @@
+#ifndef IMX_USBMISC_H
+#define IMX_USBMISC_H
+
+#include "hw/sysbus.h"
+
+enum IMXUSBMiscRegisters {
+USBMISC_NUM = 0x24 / sizeof(uint32_t) + 1,
+};
+
+typedef struct IMXUSBMiscState {
+/*< private >*/
+SysBusDevice parent_obj;
+
+/*< public >*/
+MemoryRegion iomem;
+uint32_t regs[USBMISC_NUM];
+} IMXUSBMiscState;
+
+#define TYPE_IMX_USBMISC "imx-usbmisc"
+#define IMX_USBMISC(obj) OBJECT_CHECK(IMXUSBMiscState, (obj), TYPE_IMX_USBMISC)
+
+#endif /* IMX_USBMISC_H */
-- 
2.13.5




[Qemu-devel] [PATCH v2 21/27] i.MX: Add implementation of i.MX7 GPR IP block

2017-10-23 Thread Andrey Smirnov
Add minimal code needed to allow upstream Linux guest to boot.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/misc/Makefile.objs  |   1 +
 hw/misc/imx7_gpr.c | 119 +
 include/hw/misc/imx7_gpr.h |  28 +++
 3 files changed, 148 insertions(+)
 create mode 100644 hw/misc/imx7_gpr.c
 create mode 100644 include/hw/misc/imx7_gpr.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 943b22af40..c9944161bd 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -39,6 +39,7 @@ obj-$(CONFIG_IMX) += imx2_wdt.o
 obj-$(CONFIG_IMX) += imx7_snvs.o
 obj-$(CONFIG_IMX) += imx7_iomuxc.o
 obj-$(CONFIG_IMX) += imx_flexcan.o
+obj-$(CONFIG_IMX) += imx7_gpr.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/imx7_gpr.c b/hw/misc/imx7_gpr.c
new file mode 100644
index 00..9e8ccea9e8
--- /dev/null
+++ b/hw/misc/imx7_gpr.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 GPR IP block emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * Bare minimum emulation code needed to support being able to shut
+ * down linux guest gracefully.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/misc/imx7_gpr.h"
+#include "qemu/log.h"
+#include "sysemu/sysemu.h"
+
+enum IMX7GPRRegisters {
+IOMUXC_GPR0  = 0x00,
+IOMUXC_GPR1  = 0x04,
+IOMUXC_GPR2  = 0x08,
+IOMUXC_GPR3  = 0x0c,
+IOMUXC_GPR4  = 0x10,
+IOMUXC_GPR5  = 0x14,
+IOMUXC_GPR6  = 0x18,
+IOMUXC_GPR7  = 0x1c,
+IOMUXC_GPR8  = 0x20,
+IOMUXC_GPR9  = 0x24,
+IOMUXC_GPR10 = 0x28,
+IOMUXC_GPR11 = 0x2c,
+IOMUXC_GPR12 = 0x30,
+IOMUXC_GPR13 = 0x34,
+IOMUXC_GPR14 = 0x38,
+IOMUXC_GPR15 = 0x3c,
+IOMUXC_GPR16 = 0x40,
+IOMUXC_GPR17 = 0x44,
+IOMUXC_GPR18 = 0x48,
+IOMUXC_GPR19 = 0x4c,
+IOMUXC_GPR20 = 0x50,
+IOMUXC_GPR21 = 0x54,
+IOMUXC_GPR22 = 0x58,
+};
+
+#define IMX7D_GPR1_IRQ_MASK BIT(12)
+#define IMX7D_GPR1_ENET1_TX_CLK_SEL_MASKBIT(13)
+#define IMX7D_GPR1_ENET2_TX_CLK_SEL_MASKBIT(14)
+#define IMX7D_GPR1_ENET_TX_CLK_SEL_MASK (0x3 << 13)
+#define IMX7D_GPR1_ENET1_CLK_DIR_MASK   BIT(17)
+#define IMX7D_GPR1_ENET2_CLK_DIR_MASK   BIT(18)
+#define IMX7D_GPR1_ENET_CLK_DIR_MASK(0x3 << 17)
+
+#define IMX7D_GPR5_CSI_MUX_CONTROL_MIPI BIT(4)
+#define IMX7D_GPR12_PCIE_PHY_REFCLK_SEL BIT(5)
+#define IMX7D_GPR22_PCIE_PHY_PLL_LOCKED BIT(31)
+
+
+static uint64_t imx7_gpr_read(void *opaque, hwaddr offset, unsigned size)
+{
+if (offset == IOMUXC_GPR22) {
+return IMX7D_GPR22_PCIE_PHY_PLL_LOCKED;
+}
+
+return 0;
+}
+
+static void imx7_gpr_write(void *opaque, hwaddr offset,
+   uint64_t v, unsigned size)
+{
+}
+
+static const struct MemoryRegionOps imx7_gpr_ops = {
+.read = imx7_gpr_read,
+.write = imx7_gpr_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the
+ * real device but in practice there is no reason for a guest
+ * to access this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void imx7_gpr_init(Object *obj)
+{
+SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+IMX7GPRState *s = IMX7_GPR(obj);
+
+memory_region_init_io(&s->mmio, obj, &imx7_gpr_ops, s,
+  TYPE_IMX7_GPR, 64 * 1024);
+sysbus_init_mmio(sd, &s->mmio);
+}
+
+static void imx7_gpr_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->desc  = "i.MX7 General Purpose Registers Module";
+}
+
+static const TypeInfo imx7_gpr_info = {
+.name  = TYPE_IMX7_GPR,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(IMX7GPRState),
+.instance_init = imx7_gpr_init,
+.class_init= imx7_gpr_class_init,
+};
+
+static void imx7_gpr_register_type(void)
+{
+type_register_static(&imx7_gpr_info);
+}
+type_init(imx7_gpr_register_type)
diff --git a/include/hw/misc/imx7_gpr.h b/include/hw/misc/imx7_gpr.h
new file mode 100644
index 00..e19373d274
--- /dev/null
+++ b/include/hw/misc/imx7_gpr.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 GPR IP block emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in th

[Qemu-devel] [PATCH v2 24/27] i.MX: Add code to emulate i.MX7 ADC IP block

2017-10-23 Thread Andrey Smirnov
Add minimal code needed to allow upstream Linux guest to boot.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 hw/misc/Makefile.objs  |  1 +
 hw/misc/imx7_adc.c | 99 ++
 include/hw/misc/imx7_adc.h | 22 +++
 3 files changed, 122 insertions(+)
 create mode 100644 hw/misc/imx7_adc.c
 create mode 100644 include/hw/misc/imx7_adc.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index c9944161bd..b578bd0cba 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -39,6 +39,7 @@ obj-$(CONFIG_IMX) += imx2_wdt.o
 obj-$(CONFIG_IMX) += imx7_snvs.o
 obj-$(CONFIG_IMX) += imx7_iomuxc.o
 obj-$(CONFIG_IMX) += imx_flexcan.o
+obj-$(CONFIG_IMX) += imx7_adc.o
 obj-$(CONFIG_IMX) += imx7_gpr.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
diff --git a/hw/misc/imx7_adc.c b/hw/misc/imx7_adc.c
new file mode 100644
index 00..7945e99075
--- /dev/null
+++ b/hw/misc/imx7_adc.c
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 ADC block emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/misc/imx7_adc.h"
+#include "qemu/log.h"
+
+static void imx7_adc_reset(DeviceState *dev)
+{
+IMX7ADCState *s = IMX7_ADC(dev);
+
+memset(s->regs, 0, sizeof(s->regs));
+}
+
+static uint64_t imx7_adc_read(void *opaque, hwaddr offset,
+   unsigned size)
+{
+IMX7ADCState *s = opaque;
+return s->regs[offset / sizeof(uint32_t)];
+}
+
+static void imx7_adc_write(void *opaque, hwaddr offset,
+uint64_t value, unsigned size)
+{
+IMX7ADCState *s = opaque;
+s->regs[offset / sizeof(uint32_t)] = value;
+}
+
+static const struct MemoryRegionOps imx7_adc_ops = {
+.read = imx7_adc_read,
+.write = imx7_adc_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void imx7_adc_init(Object *obj)
+{
+SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+IMX7ADCState *s = IMX7_ADC(obj);
+
+memory_region_init_io(&s->iomem,
+  obj,
+  &imx7_adc_ops,
+  s,
+  TYPE_IMX7_ADC ".iomem",
+  sizeof(s->regs));
+sysbus_init_mmio(sd, &s->iomem);
+}
+
+static const VMStateDescription vmstate_imx7_adc = {
+.name = TYPE_IMX7_ADC,
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT32_ARRAY(regs, IMX7ADCState, ADC_NUM),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static void imx7_adc_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->reset = imx7_adc_reset;
+dc->vmsd  = &vmstate_imx7_adc;
+dc->desc  = "i.MX ADC Module";
+}
+
+static const TypeInfo imx7_adc_info = {
+.name  = TYPE_IMX7_ADC,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(IMX7ADCState),
+.instance_init = imx7_adc_init,
+.class_init= imx7_adc_class_init,
+};
+
+static void imx7_adc_register_type(void)
+{
+type_register_static(&imx7_adc_info);
+}
+type_init(imx7_adc_register_type)
diff --git a/include/hw/misc/imx7_adc.h b/include/hw/misc/imx7_adc.h
new file mode 100644
index 00..4a61c52caf
--- /dev/null
+++ b/include/hw/misc/imx7_adc.h
@@ -0,0 +1,22 @@
+#ifndef IMX7_ADC_H
+#define IMX7_ADC_H
+
+#include "hw/sysbus.h"
+
+enum IMX7ADCRegisters {
+ADC_NUM = 0x130 / sizeof(uint32_t) + 1,
+};
+
+typedef struct IMX7ADCState {
+/*< private >*/
+SysBusDevice parent_obj;
+
+/*< public >*/
+MemoryRegion iomem;
+uint32_t regs[ADC_NUM];
+} IMX7ADCState;
+
+#define TYPE_IMX7_ADC "imx7-adc"
+#define IMX7_ADC(obj) OBJECT_CHECK(IMX7ADCState, (obj), TYPE_IMX7_ADC)
+
+#endif /* IMX7_ADC_H */
-- 
2.13.5




[Qemu-devel] [PATCH v2 22/27] pci: Add support for Designware IP block

2017-10-23 Thread Andrey Smirnov
Add code needed to get a functional PCI subsytem when using in
conjunction with upstream Linux guest (4.13+). Tested to work against
"e1000e" (network adapter, using MSI interrupts) as well as
"usb-ehci" (USB controller, using legacy PCI interrupts).

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Signed-off-by: Andrey Smirnov 
---
 default-configs/arm-softmmu.mak  |   2 +
 hw/pci-host/Makefile.objs|   2 +
 hw/pci-host/designware.c | 614 +++
 include/hw/pci-host/designware.h |  92 ++
 include/hw/pci/pci_ids.h |   2 +
 5 files changed, 712 insertions(+)
 create mode 100644 hw/pci-host/designware.c
 create mode 100644 include/hw/pci-host/designware.h

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index bbdd3c1d8b..225ebbd90a 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -129,3 +129,5 @@ CONFIG_ACPI=y
 CONFIG_SMBIOS=y
 CONFIG_ASPEED_SOC=y
 CONFIG_GPIO_KEY=y
+
+CONFIG_PCI_DESIGNWARE=y
diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs
index 9c7909cf44..0e2c0a123b 100644
--- a/hw/pci-host/Makefile.objs
+++ b/hw/pci-host/Makefile.objs
@@ -17,3 +17,5 @@ common-obj-$(CONFIG_PCI_PIIX) += piix.o
 common-obj-$(CONFIG_PCI_Q35) += q35.o
 common-obj-$(CONFIG_PCI_GENERIC) += gpex.o
 common-obj-$(CONFIG_PCI_XILINX) += xilinx-pcie.o
+
+common-obj-$(CONFIG_PCI_DESIGNWARE) += designware.o
diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
new file mode 100644
index 00..7ae4126d96
--- /dev/null
+++ b/hw/pci-host/designware.c
@@ -0,0 +1,614 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * Designware PCIe IP block emulation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pci/pcie_port.h"
+#include "hw/pci-host/designware.h"
+
+#define PCIE_PORT_LINK_CONTROL  0x710
+
+#define PCIE_PHY_DEBUG_R1   0x72C
+#define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP  BIT(4)
+
+#define PCIE_LINK_WIDTH_SPEED_CONTROL   0x80C
+
+#define PCIE_MSI_ADDR_LO0x820
+#define PCIE_MSI_ADDR_HI0x824
+#define PCIE_MSI_INTR0_ENABLE   0x828
+#define PCIE_MSI_INTR0_MASK 0x82C
+#define PCIE_MSI_INTR0_STATUS   0x830
+
+#define PCIE_ATU_VIEWPORT   0x900
+#define PCIE_ATU_REGION_INBOUND (0x1 << 31)
+#define PCIE_ATU_REGION_OUTBOUND(0x0 << 31)
+#define PCIE_ATU_REGION_INDEX2  (0x2 << 0)
+#define PCIE_ATU_REGION_INDEX1  (0x1 << 0)
+#define PCIE_ATU_REGION_INDEX0  (0x0 << 0)
+#define PCIE_ATU_CR10x904
+#define PCIE_ATU_TYPE_MEM   (0x0 << 0)
+#define PCIE_ATU_TYPE_IO(0x2 << 0)
+#define PCIE_ATU_TYPE_CFG0  (0x4 << 0)
+#define PCIE_ATU_TYPE_CFG1  (0x5 << 0)
+#define PCIE_ATU_CR20x908
+#define PCIE_ATU_ENABLE (0x1 << 31)
+#define PCIE_ATU_BAR_MODE_ENABLE(0x1 << 30)
+#define PCIE_ATU_LOWER_BASE 0x90C
+#define PCIE_ATU_UPPER_BASE 0x910
+#define PCIE_ATU_LIMIT  0x914
+#define PCIE_ATU_LOWER_TARGET   0x918
+#define PCIE_ATU_BUS(x) (((x) >> 24) & 0xff)
+#define PCIE_ATU_DEVFN(x)   (((x) >> 16) & 0xff)
+#define PCIE_ATU_UPPER_TARGET   0x91C
+
+static DesignwarePCIEHost *
+designware_pcie_root_to_host(DesignwarePCIERoot *root)
+{
+BusState *bus = qdev_get_parent_bus(DEVICE(root));
+return DESIGNWARE_PCIE_HOST(bus->parent);
+}
+
+static void designware_pcie_root_msi_write(void *opaque, hwaddr addr,
+   uint64_t val, unsigned len)
+{
+DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(opaque);
+DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
+
+root->msi.intr[0].status |= (1 << val) & root->msi.intr[0].enable;
+
+if (root->msi.intr[0].status

Re: [Qemu-devel] [PATCH v3 30/30] Implement support for i.MX7 Sabre board

2017-11-22 Thread Andrey Smirnov
On Tue, Nov 21, 2017 at 10:22 AM, Peter Maydell
 wrote:
> On 6 November 2017 at 15:48, Andrey Smirnov  wrote:
>> Implement code needed to set up emulation of MCIMX7SABRE board from
>> NXP. For more info about the HW see:
>>
>> https://www.nxp.com/support/developer-resources/hardware-development-tools/sabre-development-system/sabre-board-for-smart-devices-based-on-the-i.mx-7dual-applications-processors:MCIMX7SABRE
>
> You could put this URL in a comment in the code as well.
>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: Philippe Mathieu-Daudé 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  hw/arm/Makefile.objs   |   2 +-
>>  hw/arm/mcimx7d-sabre.c | 101 
>> +
>>  2 files changed, 102 insertions(+), 1 deletion(-)
>>  create mode 100644 hw/arm/mcimx7d-sabre.c
>>
>> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
>> index f379ddc74b..eb6f6c5997 100644
>> --- a/hw/arm/Makefile.objs
>> +++ b/hw/arm/Makefile.objs
>> @@ -19,5 +19,5 @@ obj-$(CONFIG_FSL_IMX31) += fsl-imx31.o kzm.o
>>  obj-$(CONFIG_FSL_IMX6) += fsl-imx6.o sabrelite.o
>>  obj-$(CONFIG_ASPEED_SOC) += aspeed_soc.o aspeed.o
>>  obj-$(CONFIG_MPS2) += mps2.o
>> -obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o
>> +obj-$(CONFIG_FSL_IMX7) += fsl-imx7.o mcimx7d-sabre.o
>>
>> diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
>> new file mode 100644
>> index 00..7ca8e668e8
>> --- /dev/null
>> +++ b/hw/arm/mcimx7d-sabre.c
>> @@ -0,0 +1,101 @@
>> +/*
>> + * Copyright (c) 2017, Impinj, Inc.
>> + *
>> + * MCIMX7D_SABRE Board System emulation.
>> + *
>> + * Author: Andrey Smirnov 
>> + *
>> + * This code is licensed under the GPL, version 2 or later.
>> + * See the file `COPYING' in the top level directory.
>> + *
>> + * It (partially) emulates a mcimx7d_sabre board, with a Freescale
>> + * i.MX7 SoC
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "qapi/error.h"
>> +#include "qemu-common.h"
>> +#include "hw/arm/fsl-imx7.h"
>> +#include "hw/boards.h"
>> +#include "sysemu/sysemu.h"
>> +#include "sysemu/device_tree.h"
>> +#include "qemu/error-report.h"
>> +#include "sysemu/qtest.h"
>> +#include "net/net.h"
>> +
>> +typedef struct {
>> +FslIMX7State soc;
>> +MemoryRegion ram;
>> +} MCIMX7Sabre;
>> +
>> +static void mcimx7d_add_psci_node(const struct arm_boot_info *boot_info,
>> +  void *fdt)
>> +{
>> +const char comp[] = "arm,psci-0.2\0arm,psci";
>> +
>> +qemu_fdt_add_subnode(fdt, "/psci");
>> +qemu_fdt_setprop(fdt, "/psci", "compatible", comp, sizeof(comp));
>> +qemu_fdt_setprop_string(fdt, "/psci", "method", "smc");
>> +}
>
> I'm still unconvinced by this (none of the other i.mx boards we have
> have anything like it).

None of the other boards are both SMP capable and support SMP in
upstream Linux only through PSCI (as it the case for i.MX7), so
comparing against the precedent is not very helpful.

> How does the real hardware boot SMP ?
>

Real hardware executes a bootloader which is expected to implement
PSCI and do the DTB fixup as I implemented above.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH v3 00/30] Initial i.MX7 support

2017-11-22 Thread Andrey Smirnov
On Tue, Nov 21, 2017 at 10:34 AM, Peter Maydell
 wrote:
> On 6 November 2017 at 15:47, Andrey Smirnov  wrote:
>> Hi everyone,
>> - Added proper USB emulation code, so now it should be possible to
>>   emulated guest's USB bus
>
> The patchset is huge as it is, if you add more stuff to it
> it makes it even more likely to sink to the bottom of my
> to-review queue...
>

USB peripheral emulation had to be a part of a patch-set, either in
dummy or a full featured form, in order to be able to boot vanilla
Linux kernel because you insisted that I don't use
"ignore_memory_transaction_failures". The reason why the dummy
emulation version of it it was not a part of v2 was because I did my
test with a bad kernel config where USB was disabled, didn't realize
USB was essential and did not write code to support it. Now, once I
realized it, I wrote a dummy version, and then later, while waiting
for v2 to be reviewed, worked on proper USB emulation the code. Said
code turned out to be comparatively trivial to the first dummy
implementation, so instead of going through the exercise of submitting
dummy first and then proper version later I squashed both and the
result in v3.


>> Peter, I didn't hear anything from you about the code of
>> mcimx7d_add_psci_node(), as discussed here:
>>
>> https://www.mail-archive.com/qemu-devel@nongnu.org/msg486874.html
>>
>> so I kept the original code intact. As I mentioned before, my goal was
>> to be able to boot into vanilla Linux kerenel and have working SMP
>> without needing to use a PSCI implementing bootloader. If that is
>> something that new board code shouldn't do, please let me know.
>
> Broadly, board code should work the same way the real hardware
> does, unless there's a clear reason why not.

Yes, this all makes sense. As far as I understand convenience being
able to boot Linux directly in QEMU has long been the "clear reason
why not". Now that certain SoC specific versions of Linux are not as
self-sufficient and can't support SMP without external help, emulating
PSCI and doing appropriate DTB fixups for that is just an adaptaion of
the old convenience mechanism to new times and circumstances, IMHO.

> "virt" is special because it writes its own dtb entirely.
>
> Maybe PSCI does need to be a different special case, since we're
> emulating part of a bootloader here.

OK, I'll ignore the "maybe" part and proceed as if we are in agreement
on PSCI for v4.

> But if so I think that code belongs more in hw/arm/boot.c, so that we 
> automatically fix up the
> dtb to say "we have psci" if we are (a) booting a kernel directly
> and (b) the CPU has the psci-conduit property set to enable QEMU's
> PSCI implementation.
>

OK, sure, makes sense. I'll change the patch to use shared
infrastructure for that.

> (Also the code in virt.c for adding a PSCI node is considerably
> fuller-featured than yours is.)
>

Okay... My code is targeting both fixed PSCI conduit (smc) and PSCI
implementation (0.2/1.0), implementing support for anything but that
in my board specific code would've been, IMHO, silly. OK, I'll
interpret that comment not as a slight, but as a request to use
virt.c's implementation for shared infrastructure.

>> Thanks,
>> Andrey Smirnov
>>
>> [v2] https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg05516.html
>> [v1] https://lists.gnu.org/archive/html/qemu-devel/2017-09/msg04770.html
>>
>>
>> Andrey Smirnov (30):
>>   imx_fec: Do not link to netdev
>>   imx_fec: Refactor imx_eth_enable_rx()
>>   imx_fec: Change queue flushing heuristics
>>   imx_fec: Use ENET_FTRL to determine truncation length
>>   imx_fec: Use MIN instead of explicit ternary operator
>>   imx_fec: Emulate SHIFT16 in ENETx_RACC
>>   imx_fec: Add support for multiple Tx DMA rings
>>   imx_fec: Use correct length for packet size
>>   imx_fec: Fix a typo in imx_enet_receive()
>>   imx_fec: Reserve full 4K page for the register file
>>   sdhci: Add i.MX specific subtype of SDHCI
>>   sdhci: Implement write method of ACMD12ERRSTS register
>
> Everything above here is pretty nearly ready to go in;
> if you send that as a patchseries then it should be easy
> to review and queue ready for 2.12 (which will open up
> for new commits in mid-december).
>

I'm not quite sure where you stand on "imx_fec: Use ENET_FTRL to
determine truncation length", but sure, sounds good, I'll prepare the
rest of them as a separate patch set and submit it, as soon as I get a
chance.

>>   i.MX: Add code to emulate i.MX7 CCM, PMU and ANALOG IP blocks
>>   i.MX: Add code to emulate i.MX2 watchdog IP block

Re: [Qemu-devel] [PATCH v3 04/30] imx_fec: Use ENET_FTRL to determine truncation length

2017-11-22 Thread Andrey Smirnov
On Tue, Nov 21, 2017 at 9:31 AM, Peter Maydell  wrote:
> On 6 November 2017 at 15:47, Andrey Smirnov  wrote:
>> Frame truncation length, TRUNC_FL, is determined by the contents of
>> ENET_FTRL register, so convert the code to use it instead of a
>> hardcoded constant.
>>
>> To avoid the case where TRUNC_FL is greater that ENET_MAX_FRAME_SIZE,
>> increase the value of the latter to its theoretical maximum of 16K.
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: Philippe Mathieu-Daudé 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  hw/net/imx_fec.c | 4 ++--
>>  include/hw/net/imx_fec.h | 3 ++-
>>  2 files changed, 4 insertions(+), 3 deletions(-)
>>
>> diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
>> index eb034ffd0c..dda0816fb3 100644
>> --- a/hw/net/imx_fec.c
>> +++ b/hw/net/imx_fec.c
>> @@ -1052,8 +1052,8 @@ static ssize_t imx_enet_receive(NetClientState *nc, 
>> const uint8_t *buf,
>>  crc_ptr = (uint8_t *) &crc;
>>
>>  /* Huge frames are truncted.  */
>> -if (size > ENET_MAX_FRAME_SIZE) {
>> -size = ENET_MAX_FRAME_SIZE;
>> +if (size > s->regs[ENET_FTRL]) {
>> +size = s->regs[ENET_FTRL];
>>  flags |= ENET_BD_TR | ENET_BD_LG;
>>  }
>>
>> diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
>> index 4bc8f03ec2..0fcc4f0c71 100644
>> --- a/include/hw/net/imx_fec.h
>> +++ b/include/hw/net/imx_fec.h
>> @@ -86,7 +86,6 @@
>>  #define ENET_TCCR3 393
>>  #define ENET_MAX   400
>>
>> -#define ENET_MAX_FRAME_SIZE2032
>>
>>  /* EIR and EIMR */
>>  #define ENET_INT_HB(1 << 31)
>> @@ -155,6 +154,8 @@
>>  #define ENET_RCR_NLC   (1 << 30)
>>  #define ENET_RCR_GRS   (1 << 31)
>>
>> +#define ENET_MAX_FRAME_SIZE(1 << ENET_RCR_MAX_FL_LENGTH)
>
> This means we now have functions with 16K local array
> variables on the stack, which seems like a bad idea.
>

Can't say I see a big difference between having a 2K vs 16K buffer on
the stack, but regardless, I am not quite clear if you are not too hot
about this patch and want me to drop it (I am fine with it) or do you
want me to modify it to have the emulation layer allocate said 16K
buffer on the heap instead of a stack?

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH v3 03/30] imx_fec: Change queue flushing heuristics

2017-11-22 Thread Andrey Smirnov
On Tue, Nov 21, 2017 at 9:27 AM, Peter Maydell  wrote:
> On 6 November 2017 at 15:47, Andrey Smirnov  wrote:
>> In current implementation, packet queue flushing logic seem to suffer
>> from a deadlock like scenario if a packet is received by the interface
>> before before Rx ring is initialized by Guest's driver. Consider the
>> following sequence of events:
>>
>> 1. A QEMU instance is started against a TAP device on Linux
>>host, running Linux guest, e. g., something to the effect
>>of:
>>
>>qemu-system-arm \
>>   -net nic,model=imx.fec,netdev=lan0 \
>>   netdev tap,id=lan0,ifname=tap0,script=no,downscript=no \
>>   ... rest of the arguments ...
>>
>> 2. Once QEMU starts, but before guest reaches the point where
>>FEC deriver is done initializing the HW, Guest, via TAP
>>interface, receives a number of multicast MDNS packets from
>>Host (not necessarily true for every OS, but it happens at
>>least on Fedora 25)
>>
>> 3. Recieving a packet in such a state results in
>>imx_eth_can_receive() returning '0', which in turn causes
>>tap_send() to disable corresponding event (tap.c:203)
>>
>> 4. Once Guest's driver reaches the point where it is ready to
>>recieve packets it prepares Rx ring descriptors and writes
>>ENET_RDAR_RDAR to ENET_RDAR register to indicate to HW that
>>more descriptors are ready. And at this points emulation
>>layer does this:
>>
>>  s->regs[index] = ENET_RDAR_RDAR;
>>  imx_eth_enable_rx(s);
>>
>>which, combined with:
>>
>>   if (!s->regs[ENET_RDAR]) {
>>  qemu_flush_queued_packets(qemu_get_queue(s->nic));
>>   }
>>
>>results in Rx queue never being flushed and corresponding
>>I/O event beign disabled.
>>
>> To prevent the problem, change the code to always flush packet queue
>> when ENET_RDAR transitions 0 -> ENET_RDAR_RDAR.
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: Philippe Mathieu-Daudé 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
>> index 62ad473b05..4bc8f03ec2 100644
>> --- a/include/hw/net/imx_fec.h
>> +++ b/include/hw/net/imx_fec.h
>> @@ -252,6 +252,7 @@ typedef struct IMXFECState {
>>  uint32_t phy_int_mask;
>>
>>  bool is_fec;
>> +bool needs_flush;
>>  } IMXFECState;
>
> This field isn't needed any more in this version of the patch, I think?
>

Yeah, my bad, forgot to remove this part. Will do in v4.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH v3 07/30] imx_fec: Add support for multiple Tx DMA rings

2017-11-22 Thread Andrey Smirnov
On Tue, Nov 21, 2017 at 9:44 AM, Peter Maydell  wrote:
> On 6 November 2017 at 15:47, Andrey Smirnov  wrote:
>> More recent version of the IP block support more than one Tx DMA ring,
>> so add the code implementing that feature.
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: Philippe Mathieu-Daudé 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>
>>  static const VMStateDescription vmstate_imx_eth = {
>>  .name = TYPE_IMX_FEC,
>> -.version_id = 2,
>> -.minimum_version_id = 2,
>> +.version_id = 3,
>> +.minimum_version_id = 3,
>>  .fields = (VMStateField[]) {
>>  VMSTATE_UINT32_ARRAY(regs, IMXFECState, ENET_MAX),
>>  VMSTATE_UINT32(rx_descriptor, IMXFECState),
>> -VMSTATE_UINT32(tx_descriptor, IMXFECState),
>> -
>> +VMSTATE_UINT32_ARRAY(tx_descriptor, IMXFECState, ENET_TX_RING_NUM),
>> +VMSTATE_UINT32(tx_ring_num, IMXFECState),
>>  VMSTATE_UINT32(phy_status, IMXFECState),
>>  VMSTATE_UINT32(phy_control, IMXFECState),
>>  VMSTATE_UINT32(phy_advertise, IMXFECState),
>
> tx_ring_num is constant for any particular instantiation of the device,
> so you don't need to put it in the vmstate.
>
> It's pretty trivial to make this vmstate compatible with the old
> ones for the existing single-tx-descriptor devices, so we might as well:
>
> /* Versions of this device with more than one TX descriptor
>  * save the 2nd and 3rd descriptors in a subsection, to maintain
>  * migration compatibility with previous versions of the device
>  * that only supported a single descriptor.
>  */
> static bool txdescs_needed(void *opaque) {
> IMXFECState *s = opaque;
>
> return s->tx_ring_num > 1;
> }
>
> static const VMStateDescription vmstate_imx_eth_txdescs = {
> .name = "imx.fec/txdescs",
> .version_id = 1,
> .minimum_version_id = 1,
> .needed = txdescs_needed,
> .fields = (VMStateField[]) {
>  VMSTATE_UINT32(tx_descriptor[1], IMXFECState),
>  VMSTATE_UINT32(tx_descriptor[2], IMXFECState),
>  VMSTATE_END_OF_LIST()
> }
> };
>
> and then add this to the vmx_state_eth at the end:
> .subsections = (const VMStateDescription*[]) {
>  &vmstate_imx_eth_txdescs,
>  NULL
> }
>
> Then you don't need to bump version_id/minimum_version_id on the
> vmstate_imx_eth struct.
>

Cool, sounds good. Will add that to the patch in v4.

>> @@ -791,6 +821,7 @@ static void imx_eth_write(void *opaque, hwaddr offset, 
>> uint64_t value,
>> unsigned size)
>>  {
>>  IMXFECState *s = IMX_FEC(opaque);
>> +const bool single_tx_ring = s->tx_ring_num != 3;
>
> This looks odd -- I would have expected "single_tx_ring =
> s->tx_ring_num == 1" ...

AFAIK the HW that's out there will have either 3 or 1 Tx ring, so
that's why I wrote it this way. I'll change the logic to the way your
suggest to avoid surprising the reader.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH v3 10/30] imx_fec: Reserve full 4K page for the register file

2017-11-22 Thread Andrey Smirnov
On Tue, Nov 21, 2017 at 9:48 AM, Peter Maydell  wrote:
> On 6 November 2017 at 15:47, Andrey Smirnov  wrote:
>> Some i.MX SoCs (e.g. i.MX7) have FEC registers going as far as offset
>> 0x614, so to avoid getting aborts when accessing those on QEMU, extend
>> the register file to cover 4KB of address space instead of just 1K.
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: Philippe Mathieu-Daudé 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  hw/net/imx_fec.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
>> index 48d012cad6..e236bc933c 100644
>> --- a/hw/net/imx_fec.c
>> +++ b/hw/net/imx_fec.c
>> @@ -1252,7 +1252,7 @@ static void imx_eth_realize(DeviceState *dev, Error 
>> **errp)
>>  SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
>>
>>  memory_region_init_io(&s->iomem, OBJECT(dev), &imx_eth_ops, s,
>> -  TYPE_IMX_FEC, 0x400);
>> +  TYPE_IMX_FEC, 0x1000);
>>  sysbus_init_mmio(sbd, &s->iomem);
>>  sysbus_init_irq(sbd, &s->irq[0]);
>>  sysbus_init_irq(sbd, &s->irq[1]);
>> --
>
> I notice that we have an unused #define FSL_IMX25_FEC_SIZE 0x4000 in
> fsl-imx25.h, and the Linux device trees for the imx25 define the size
> of the FEC register block as 0x4000. Should this be 0x4000 ?
>

I think the size reserved for that register file differs between
differen SoC. E.g. it's 16K on i.MX25, as you pointed out, but 64K on
i.MX7. It's all the same to me as long as it's greater than 0x1000.
I'll change the code to use FSL_IMX25_FEC_SIZE since it gets rid of a
magic number.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH v3 11/30] sdhci: Add i.MX specific subtype of SDHCI

2017-11-22 Thread Andrey Smirnov
On Tue, Nov 21, 2017 at 10:02 AM, Peter Maydell
 wrote:
> On 6 November 2017 at 15:47, Andrey Smirnov  wrote:
>> IP block found on several generations of i.MX family does not use
>> vanilla SDHCI implementation and it comes with a number of quirks.
>>
>> Introduce i.MX SDHCI subtype of SDHCI block to add code necessary to
>> support unmodified Linux guest driver.
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: Philippe Mathieu-Daudé 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>
> Hi. Mostly this looks ok; some comments below.
>
>> ---
>>  hw/sd/sdhci-internal.h |  15 ++
>>  hw/sd/sdhci.c  | 127 
>> -
>>  include/hw/sd/sdhci.h  |   8 
>>  3 files changed, 148 insertions(+), 2 deletions(-)
>>
>> diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
>> index 161177cf39..2a1b4b06ee 100644
>> --- a/hw/sd/sdhci-internal.h
>> +++ b/hw/sd/sdhci-internal.h
>> @@ -91,6 +91,8 @@
>>  #define SDHC_CTRL_ADMA2_32 0x10
>>  #define SDHC_CTRL_ADMA2_64 0x18
>>  #define SDHC_DMA_TYPE(x)   ((x) & SDHC_CTRL_DMA_CHECK_MASK)
>> +#define SDHC_CTRL_4BITBUS  0x02
>> +#define SDHC_CTRL_8BITBUS  0x20
>>
>>  /* R/W Power Control Register 0x0 */
>>  #define SDHC_PWRCON0x29
>> @@ -229,4 +231,17 @@ enum {
>>
>>  extern const VMStateDescription sdhci_vmstate;
>>
>> +
>> +#define ESDHC_MIX_CTRL  0x48
>> +#define ESDHC_VENDOR_SPEC   0xc0
>> +#define ESDHC_DLL_CTRL  0x60
>> +
>> +#define ESDHC_TUNING_CTRL   0xcc
>> +#define ESDHC_TUNE_CTRL_STATUS  0x68
>> +#define ESDHC_WTMK_LVL  0x44
>> +
>> +#define ESDHC_CTRL_4BITBUS  (0x1 << 1)
>> +#define ESDHC_CTRL_8BITBUS  (0x2 << 1)
>> +
>> +
>>  #endif
>> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
>> index 6d6a791ee9..f561cc44e3 100644
>> --- a/hw/sd/sdhci.c
>> +++ b/hw/sd/sdhci.c
>> @@ -265,7 +265,8 @@ static void sdhci_send_command(SDHCIState *s)
>>  }
>>  }
>>
>> -if ((s->norintstsen & SDHC_NISEN_TRSCMP) &&
>> +if (!(s->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) &&
>> +(s->norintstsen & SDHC_NISEN_TRSCMP) &&
>>  (s->cmdreg & SDHC_CMD_RESPONSE) == SDHC_CMD_RSP_WITH_BUSY) {
>>  s->norintsts |= SDHC_NIS_TRSCMP;
>>  }
>> @@ -1191,6 +1192,8 @@ static void sdhci_initfn(SDHCIState *s)
>>
>>  s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 
>> sdhci_raise_insertion_irq, s);
>>  s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 
>> sdhci_data_transfer, s);
>> +
>> +s->io_ops = &sdhci_mmio_ops;
>>  }
>>
>>  static void sdhci_uninitfn(SDHCIState *s)
>> @@ -1347,7 +1350,7 @@ static void sdhci_sysbus_realize(DeviceState *dev, 
>> Error ** errp)
>>  s->buf_maxsz = sdhci_get_fifolen(s);
>>  s->fifo_buffer = g_malloc0(s->buf_maxsz);
>>  sysbus_init_irq(sbd, &s->irq);
>> -memory_region_init_io(&s->iomem, OBJECT(s), &sdhci_mmio_ops, s, "sdhci",
>> +memory_region_init_io(&s->iomem, OBJECT(s), s->io_ops, s, "sdhci",
>>  SDHC_REGISTERS_MAP_SIZE);
>>  sysbus_init_mmio(sbd, &s->iomem);
>>  }
>> @@ -1386,11 +1389,131 @@ static const TypeInfo sdhci_bus_info = {
>>  .class_init = sdhci_bus_class_init,
>>  };
>>
>> +static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
>> +{
>> +SDHCIState *s = SYSBUS_SDHCI(opaque);
>> +uint32_t ret;
>> +uint16_t hostctl;
>> +
>> +switch (offset) {
>> +default:
>> +return sdhci_read(opaque, offset, size);
>> +
>> +case SDHC_HOSTCTL:
>> +hostctl = SDHC_DMA_TYPE(s->hostctl) << 5;
>> +
>> +if (s->hostctl & SDHC_CTRL_8BITBUS) {
>> +hostctl |= ESDHC_CTRL_8BITBUS;
>> +}
>> +
>> +if (s->hostctl & SDHC_CTRL_4BITBUS) {
>> +hostctl |= ESDHC_CTRL_4BITBUS;
>> +}
>> +
>> +ret = hostctl | (s->blkgap << 16) |
>> +(s->wakcon << 24);
>

Re: [Qemu-devel] [PATCH v3 12/30] sdhci: Implement write method of ACMD12ERRSTS register

2017-11-22 Thread Andrey Smirnov
On Tue, Nov 21, 2017 at 10:04 AM, Peter Maydell
 wrote:
> On 6 November 2017 at 15:47, Andrey Smirnov  wrote:
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: Philippe Mathieu-Daudé 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  hw/sd/sdhci.c | 3 +++
>>  1 file changed, 3 insertions(+)
>>
>> diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
>> index f561cc44e3..53e5e011a7 100644
>> --- a/hw/sd/sdhci.c
>> +++ b/hw/sd/sdhci.c
>> @@ -1139,6 +1139,9 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, 
>> unsigned size)
>>  s->admasysaddr = (s->admasysaddr & (0xULL |
>>  ((uint64_t)mask << 32))) | ((uint64_t)value << 32);
>>  break;
>> +case SDHC_ACMD12ERRSTS:
>> +MASKED_WRITE(s->acmd12errsts, mask, value);
>> +break;
>>  case SDHC_FEAER:
>>  s->acmd12errsts |= value;
>>  s->errintsts |= (value >> 16) & s->errintstsen;
>> --
>> 2.13.6
>
> Is this part of the stock SDHCI spec that we just forgot to implement?

Yes it is. I don't know if missing that code critical for anything,
but since the rest of the plumbing is there I thought that we may as
well implement it.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH v3 13/30] i.MX: Add code to emulate i.MX7 CCM, PMU and ANALOG IP blocks

2017-11-22 Thread Andrey Smirnov
On Tue, Nov 21, 2017 at 10:08 AM, Peter Maydell
 wrote:
> On 6 November 2017 at 15:47, Andrey Smirnov  wrote:
>> Add minimal code needed to allow upstream Linux guest to boot.
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: Philippe Mathieu-Daudé 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  hw/misc/Makefile.objs  |   1 +
>>  hw/misc/imx7_ccm.c | 233 
>> +
>>  include/hw/misc/imx7_ccm.h | 130 +
>>  3 files changed, 364 insertions(+)
>>  create mode 100644 hw/misc/imx7_ccm.c
>>  create mode 100644 include/hw/misc/imx7_ccm.h
>>
>> diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
>> index 29fb922cef..ac1be05a03 100644
>> --- a/hw/misc/Makefile.objs
>> +++ b/hw/misc/Makefile.objs
>> @@ -34,6 +34,7 @@ obj-$(CONFIG_IMX) += imx31_ccm.o
>>  obj-$(CONFIG_IMX) += imx25_ccm.o
>>  obj-$(CONFIG_IMX) += imx6_ccm.o
>>  obj-$(CONFIG_IMX) += imx6_src.o
>> +obj-$(CONFIG_IMX) += imx7_ccm.o
>>  obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
>>  obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
>>  obj-$(CONFIG_MAINSTONE) += mst_fpga.o
>> diff --git a/hw/misc/imx7_ccm.c b/hw/misc/imx7_ccm.c
>> new file mode 100644
>> index 00..2876164cfa
>> --- /dev/null
>> +++ b/hw/misc/imx7_ccm.c
>> @@ -0,0 +1,233 @@
>> +/*
>> + * Copyright (c) 2017, Impinj, Inc.
>> + *
>> + * i.MX7 CCM, PMU and ANALOG IP blocks emulation code
>
> Should these really all be in one single device rather
> than one device per IP block ?
>

They all share the same register write semantics,
imx7_set_clr_tog_write, so I'd like to keep them in the same file. But
other than that, they can be split into all sorts of configurations.
As far as memory map in i.MX7 RM is concerned "CCM" and "Analog" are
distinct register files where the rest of them ("digiprog", "pmu") are
"sub-blocks" of those two (or at least that's my interpretation). I'll
change v4 to have that split.

If you want me to convert every block _and_ sub-block into a
standalone device, let me know.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH v3 14/30] i.MX: Add code to emulate i.MX2 watchdog IP block

2017-11-22 Thread Andrey Smirnov
On Tue, Nov 21, 2017 at 10:10 AM, Peter Maydell
 wrote:
> On 6 November 2017 at 15:47, Andrey Smirnov  wrote:
>> Add enough code to emulate i.MX2 watchdog IP block so it would be
>> possible to reboot the machine running Linux Guest.
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: Philippe Mathieu-Daudé 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  hw/misc/Makefile.objs  |  1 +
>>  hw/misc/imx2_wdt.c | 88 
>> ++
>>  include/hw/misc/imx2_wdt.h | 34 ++
>>  3 files changed, 123 insertions(+)
>>  create mode 100644 hw/misc/imx2_wdt.c
>>  create mode 100644 include/hw/misc/imx2_wdt.h
>>
>> diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
>> index ac1be05a03..c393a93456 100644
>> --- a/hw/misc/Makefile.objs
>> +++ b/hw/misc/Makefile.objs
>> @@ -35,6 +35,7 @@ obj-$(CONFIG_IMX) += imx25_ccm.o
>>  obj-$(CONFIG_IMX) += imx6_ccm.o
>>  obj-$(CONFIG_IMX) += imx6_src.o
>>  obj-$(CONFIG_IMX) += imx7_ccm.o
>> +obj-$(CONFIG_IMX) += imx2_wdt.o
>>  obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
>>  obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
>>  obj-$(CONFIG_MAINSTONE) += mst_fpga.o
>> diff --git a/hw/misc/imx2_wdt.c b/hw/misc/imx2_wdt.c
>> new file mode 100644
>> index 00..3a1c33aa51
>> --- /dev/null
>> +++ b/hw/misc/imx2_wdt.c
>> @@ -0,0 +1,88 @@
>> +/*
>> + * Copyright (c) 2017, Impinj, Inc.
>> + *
>> + * i.MX2 Watchdog IP block
>> + *
>> + * Author: Andrey Smirnov 
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
>> + * See the COPYING file in the top-level directory.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "sysemu/watchdog.h"
>> +
>> +#include "hw/misc/imx2_wdt.h"
>> +
>> +#define IMX2_WDT_WCR_WDABIT(5)  /* -> External Reset WDOG_B */
>> +#define IMX2_WDT_WCR_SRSBIT(4)  /* -> Software Reset Signal */
>> +
>> +static uint64_t imx2_wdt_read(void *opaque, hwaddr addr,
>> +  unsigned int size)
>> +{
>> +return 0;
>> +}
>> +
>> +static void imx2_wdt_write(void *opaque, hwaddr addr,
>> +   uint64_t value, unsigned int size)
>> +{
>> +if (addr == IMX2_WDT_WCR &&
>> +(value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))) {
>> +watchdog_perform_action();
>> +}
>> +}
>> +
>> +static const MemoryRegionOps imx2_wdt_ops = {
>> +.read  = imx2_wdt_read,
>> +.write = imx2_wdt_write,
>> +.endianness = DEVICE_NATIVE_ENDIAN,
>> +.impl = {
>> +/*
>> + * Our device would not work correctly if the guest was doing
>> + * unaligned access. This might not be a limitation on the
>> + * real device but in practice there is no reason for a guest
>> + * to access this device unaligned.
>> + */
>> +.min_access_size = 4,
>> +.max_access_size = 4,
>> +.unaligned = false,
>> +},
>> +};
>> +
>> +static void imx2_wdt_realize(DeviceState *dev, Error **errp)
>> +{
>> +IMX2WdtState *s = IMX2_WDT(dev);
>> +
>> +memory_region_init_io(&s->mmio, OBJECT(dev),
>> +  &imx2_wdt_ops, s,
>> +  TYPE_IMX2_WDT".mmio",
>> +  IMX2_WDT_REG_NUM * sizeof(uint16_t));
>> +sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
>> +}
>> +
>> +static void imx2_wdt_class_init(ObjectClass *klass, void *data)
>> +{
>> +DeviceClass *dc = DEVICE_CLASS(klass);
>> +
>> +dc->realize = imx2_wdt_realize;
>> +set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>> +}
>> +
>> +static const TypeInfo imx2_wdt_info = {
>> +.name  = TYPE_IMX2_WDT,
>> +.parent= TYPE_SYS_BUS_DEVICE,
>> +.instance_size = sizeof(IMX2WdtState),
>> +.class_init= imx2_wdt_class_init,
>> +};
>> +
>> +static WatchdogTimerModel model = {
>> +.wdt_name = "imx2-watchdog",
>> +.wdt_description = "i.MX2 Watchdog",
>> +};
>> +
>> +static void imx2_wdt_register_type(void)
>> +{
>> +watchdog_add_model(&model);
>> +type_register_static(&imx2_wdt_info);
>> +}
>> +type_init(imx2_wdt_register_type)
>> diff --git a/include/hw/misc/imx2_wdt.h b/include/hw/misc/imx2_wdt.h
>> new file mode 100644
>> index 00..e67ac6939d
>> --- /dev/null
>> +++ b/include/hw/misc/imx2_wdt.h
>> @@ -0,0 +1,34 @@
>> +/*
>> + * Copyright (c) 2017, Impinj, Inc.
>> + *
>> + * i.MX2 Watchdog IP block
>> + *
>> + * Author: Andrey Smirnov 
>> + *
>> + * 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 IMX2_WDT_H
>> +#define IMX2_WDT_H
>> +
>> +#include "qemu/bitops.h"
>> +#include "hw/sysbus.h"
>
> The bitops.h include should be in the .c file, not here.
>

Will fix in v4.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH v3 19/30] i.MX: Add code to emulate SDMA IP block

2017-11-22 Thread Andrey Smirnov
On Tue, Nov 21, 2017 at 10:20 AM, Peter Maydell
 wrote:
> On 6 November 2017 at 15:48, Andrey Smirnov  wrote:
>> Add minimal code needed to allow upstream Linux guest to boot.
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: Philippe Mathieu-Daudé 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  hw/dma/Makefile.objs  |  1 +
>>  hw/dma/imx_sdma.c | 99 
>> +++
>>  include/hw/dma/imx_sdma.h | 22 +++
>>  3 files changed, 122 insertions(+)
>>  create mode 100644 hw/dma/imx_sdma.c
>>  create mode 100644 include/hw/dma/imx_sdma.h
>>
>
> Does Linux really insist on reads-as-written behaviour?
> (ie can you get away with just using
> create_unimplemented_device() ?)
>

Not sure. I'll give it a try for v4.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH v3 29/30] i.MX: Add i.MX7 SOC implementation.

2017-11-22 Thread Andrey Smirnov
On Wed, Nov 22, 2017 at 7:34 AM, Igor Mammedov  wrote:
> On Mon,  6 Nov 2017 07:48:12 -0800
> Andrey Smirnov  wrote:
>
>> The following interfaces are partially or fully emulated:
>>
>> * up to 2 Cortex A9 cores (SMP works with PSCI)
>> * A7 MPCORE (identical to A15 MPCORE)
>> * 4 GPTs modules
>> * 7 GPIO controllers
>> * 2 IOMUXC controllers
>> * 1 CCM module
>> * 1 SVNS module
>> * 1 SRC module
>> * 1 GPCv2 controller
>> * 4 eCSPI controllers
>> * 4 I2C controllers
>> * 7 i.MX UART controllers
>> * 2 FlexCAN controllers
>> * 2 Ethernet controllers (FEC)
>> * 3 SD controllers (USDHC)
>> * 4 WDT modules
>> * 1 SDMA module
>> * 1 GPR module
>> * 2 USBMISC modules
>> * 2 ADC modules
>> * 1 PCIe controller
>>
>> Tested to boot and work with upstream Linux (4.13+) guest.
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: Philippe Mathieu-Daudé 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
> ...
>> +
>> +static void fsl_imx7_init(Object *obj)
>> +{
>> +BusState *sysbus = sysbus_get_default();
>> +FslIMX7State *s = FSL_IMX7(obj);
>> +char name[NAME_SIZE];
>> +int i;
>> +
>> +if (smp_cpus > FSL_IMX7_NUM_CPUS) {
>> +error_report("%s: Only %d CPUs are supported (%d requested)",
>> + TYPE_FSL_IMX7, FSL_IMX7_NUM_CPUS, smp_cpus);
>> +exit(1);
>> +}
>> +
>> +for (i = 0; i < smp_cpus; i++) {
>> +object_initialize(&s->cpu[i], sizeof(s->cpu[i]),
>> +  "cortex-a7-" TYPE_ARM_CPU);
> pls reuse ARM_CPU_TYPE_NAME() macro here

Will do in v4.

Thanks,
Andrey Smirnov



[Qemu-devel] [PATCH] fsl_etsec: Fix Tx BD ring wrapping handling

2016-12-20 Thread Andrey Smirnov
Current code that handles Tx buffer desciprtor ring scanning employs the
following algorithm:

1. Restore current buffer descriptor pointer from TBPTRn

2. Process current descriptor

3. If current descriptor has BD_WRAP flag set set current
   descriptor pointer to start of the descriptor ring

4. If current descriptor points to start of the ring exit the
   loop, otherwise increment current descriptor pointer and go
   to #2

5. Store current descriptor in TBPTRn

As it can be seen the way the code is implemented results in buffer
descriptor ring being scanned starting at offset/descriptor #0. While
covering proverbial "99%" of the cases, this algorithm becomes
problematic for a number of edge cases.

Consider the following scenario: guest OS driver initializes descriptor
ring to N individual descriptors and starts sending data out. Depending
on the volume of traffic and probably guest OS driver implementation it
is possible that an edge case where a packet, spread across 2
descriptors is placed in descriptors N - 1 and 0 in that order(it is
easy to imagine similar examples involving more than 2 descriptors).

What happens then is aforementioned algorithm starts at descriptor 0,
sees a descriptor marked as BD_LAST, which it happily sends out as a
separate packet(very much malformed at this point) then the iteration
continues and the first part of the original packet is tacked to the
next transmission which ends up being bogus as well.

This behvaiour can be pretty reliably observed when scp'ing data from a
guest OS via TAP interface for files larger than 160K (every time for
700K+).

This patch changes the scanning algorithm to do the following:

1. Restore "current" and "start" buffer descriptor pointer from
   TBPTRn

2. If "current" descriptor has BD_WRAP flag set "next"
   descriptor pointer to start of the descriptor ring otherwise
   set "next" to descriptor right after "current"

3. Process current descriptor

4. If current descriptore has BD_LAST(end of a packet) set save
   "next" descriptor pointer in TBPTRn

5. Set "current" descriptor pointer to "next"

6. If "current" descriptor points to "start" (from #1) exit the loop
   loop, otherwise go to #2

This way emulation code always keeps track where guest OS driver was
driving data to last while still going full "loop" over every descriptor
in a ring, which, hopefully, should fix any potential "wrapping" issues.

Signed-off-by: Andrey Smirnov 
---
 hw/net/fsl_etsec/rings.c | 40 +---
 1 file changed, 25 insertions(+), 15 deletions(-)

diff --git a/hw/net/fsl_etsec/rings.c b/hw/net/fsl_etsec/rings.c
index 54c0127..3aebd59 100644
--- a/hw/net/fsl_etsec/rings.c
+++ b/hw/net/fsl_etsec/rings.c
@@ -332,7 +332,7 @@ static void process_tx_bd(eTSEC *etsec,
 void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr)
 {
 hwaddrring_base = 0;
-hwaddrbd_addr   = 0;
+hwaddrbd_addr, bd_addr_start, bd_addr_next;
 eTSEC_rxtx_bd bd;
 uint16_t  bd_flags;
 
@@ -343,7 +343,7 @@ void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr)
 
 ring_base = (hwaddr)(etsec->regs[TBASEH].value & 0xF) << 32;
 ring_base += etsec->regs[TBASE0 + ring_nbr].value & ~0x7;
-bd_addr= etsec->regs[TBPTR0 + ring_nbr].value & ~0x7;
+bd_addr_start = bd_addr = etsec->regs[TBPTR0 + ring_nbr].value & ~0x7;
 
 do {
 read_buffer_descriptor(etsec, bd_addr, &bd);
@@ -358,26 +358,36 @@ void etsec_walk_tx_ring(eTSEC *etsec, int ring_nbr)
 /* Save flags before BD update */
 bd_flags = bd.flags;
 
-if (bd_flags & BD_TX_READY) {
-process_tx_bd(etsec, &bd);
-
-/* Write back BD after update */
-write_buffer_descriptor(etsec, bd_addr, &bd);
-}
-
 /* Wrap or next BD */
 if (bd_flags & BD_WRAP) {
-bd_addr = ring_base;
+bd_addr_next = ring_base;
 } else {
-bd_addr += sizeof(eTSEC_rxtx_bd);
+bd_addr_next = bd_addr + sizeof(eTSEC_rxtx_bd);
 }
 
-} while (bd_addr != ring_base);
+if (bd_flags & BD_TX_READY) {
+if (bd_flags & BD_LAST) {
+/* If we encounter a descriptor marking end of a
+ * packet - save a pointer to descriptor after that as
+ * a place to resume descriptor processing for next
+ * time.
+ *
+ * As we iterate through a ring we progressively move
+ * this point forward and at the end of one cycle end
+ * up with the position ri

Re: [Qemu-devel] [PATCH v4 09/14] pci: Add support for Designware IP block

2018-01-30 Thread Andrey Smirnov
On Tue, Jan 30, 2018 at 5:18 AM, Marcel Apfelbaum
 wrote:
> Hi Andrei,
>
> Sorry for letting you wait,
> I have some comments/questions below.
>
>
> On 16/01/2018 3:37, Andrey Smirnov wrote:
>>
>> Add code needed to get a functional PCI subsytem when using in
>> conjunction with upstream Linux guest (4.13+). Tested to work against
>> "e1000e" (network adapter, using MSI interrupts) as well as
>> "usb-ehci" (USB controller, using legacy PCI interrupts).
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: Philippe Mathieu-Daudé 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Signed-off-by: Andrey Smirnov 
>> ---
>>   default-configs/arm-softmmu.mak  |   2 +
>>   hw/pci-host/Makefile.objs|   2 +
>>   hw/pci-host/designware.c | 618
>> +++
>>   include/hw/pci-host/designware.h |  93 ++
>>   include/hw/pci/pci_ids.h |   2 +
>>   5 files changed, 717 insertions(+)
>>   create mode 100644 hw/pci-host/designware.c
>>   create mode 100644 include/hw/pci-host/designware.h
>>
>> diff --git a/default-configs/arm-softmmu.mak
>> b/default-configs/arm-softmmu.mak
>> index b0d6e65038..0c5ae914ed 100644
>> --- a/default-configs/arm-softmmu.mak
>> +++ b/default-configs/arm-softmmu.mak
>> @@ -132,3 +132,5 @@ CONFIG_GPIO_KEY=y
>>   CONFIG_MSF2=y
>>   CONFIG_FW_CFG_DMA=y
>>   CONFIG_XILINX_AXI=y
>> +CONFIG_PCI_DESIGNWARE=y
>> +
>> diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs
>> index 9c7909cf44..0e2c0a123b 100644
>> --- a/hw/pci-host/Makefile.objs
>> +++ b/hw/pci-host/Makefile.objs
>> @@ -17,3 +17,5 @@ common-obj-$(CONFIG_PCI_PIIX) += piix.o
>>   common-obj-$(CONFIG_PCI_Q35) += q35.o
>>   common-obj-$(CONFIG_PCI_GENERIC) += gpex.o
>>   common-obj-$(CONFIG_PCI_XILINX) += xilinx-pcie.o
>> +
>> +common-obj-$(CONFIG_PCI_DESIGNWARE) += designware.o
>> diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
>> new file mode 100644
>> index 00..98fff5e5f3
>> --- /dev/null
>> +++ b/hw/pci-host/designware.c
>> @@ -0,0 +1,618 @@
>> +/*
>> + * Copyright (c) 2017, Impinj, Inc.
>
> 2018 :)
>
>> + *
>> + * Designware PCIe IP block emulation
>> + *
>> + * This library is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU Lesser General Public
>> + * License as published by the Free Software Foundation; either
>> + * version 2 of the License, or (at your option) any later version.
>> + *
>> + * This library 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
>> + * Lesser General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU Lesser General Public
>> + * License along with this library; if not, see
>> + * <http://www.gnu.org/licenses/>.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "qapi/error.h"
>> +#include "hw/pci/msi.h"
>> +#include "hw/pci/pci_bridge.h"
>> +#include "hw/pci/pci_host.h"
>> +#include "hw/pci/pcie_port.h"
>> +#include "hw/pci-host/designware.h"
>> +
>> +#define PCIE_PORT_LINK_CONTROL  0x710
>> +
>> +#define PCIE_PHY_DEBUG_R1   0x72C
>> +#define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP  BIT(4)
>> +
>> +#define PCIE_LINK_WIDTH_SPEED_CONTROL   0x80C
>> +
>> +#define PCIE_MSI_ADDR_LO0x820
>> +#define PCIE_MSI_ADDR_HI0x824
>> +#define PCIE_MSI_INTR0_ENABLE   0x828
>> +#define PCIE_MSI_INTR0_MASK 0x82C
>> +#define PCIE_MSI_INTR0_STATUS   0x830
>> +
>> +#define PCIE_ATU_VIEWPORT   0x900
>> +#define PCIE_ATU_REGION_INBOUND (0x1 << 31)
>> +#define PCIE_ATU_REGION_OUTBOUND(0x0 << 31)
>> +#define PCIE_ATU_REGION_INDEX2  (0x2 << 0)
>> +#define PCIE_ATU_REGION_INDEX1  (0x1 << 0)
>> +#define PCIE_ATU_REGION_INDEX0  (0x0 << 0)
>> +#define PCIE_ATU_CR10x904
>> +#define PCIE_ATU_TYPE_MEM   (0x0 << 0)
>> +#define PCIE_ATU_TYPE_IO(0x2 << 0)
>> +#define PCIE_ATU_TYPE_CFG0  (0x4 << 0)
>> +#define PCIE_ATU_TYPE_CFG1   

Re: [Qemu-devel] [PATCH v4 05/14] i.MX: Add code to emulate i.MX7 SNVS IP-block

2018-02-06 Thread Andrey Smirnov
On Wed, Jan 31, 2018 at 9:10 AM, Philippe Mathieu-Daudé  wrote:
> On 01/15/2018 10:37 PM, Andrey Smirnov wrote:
>> Add code to emulate SNVS IP-block. Currently only the bits needed to
>> be able to emulate machine shutdown are implemented.
>>
>> Cc: Peter Maydell 
>> Cc: Jason Wang 
>> Cc: Philippe Mathieu-Daudé 
>> Cc: qemu-devel@nongnu.org
>> Cc: qemu-...@nongnu.org
>> Cc: yurov...@gmail.com
>> Reviewed-by: Peter Maydell 
>> Signed-off-by: Andrey Smirnov 
>> ---
>>  hw/misc/Makefile.objs   |  1 +
>>  hw/misc/imx7_snvs.c | 83 
>> +
>>  include/hw/misc/imx7_snvs.h | 35 +++
>>  3 files changed, 119 insertions(+)
>>  create mode 100644 hw/misc/imx7_snvs.c
>>  create mode 100644 include/hw/misc/imx7_snvs.h
>>
>> diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
>> index 4b2b705a6c..019886912c 100644
>> --- a/hw/misc/Makefile.objs
>> +++ b/hw/misc/Makefile.objs
>> @@ -35,6 +35,7 @@ obj-$(CONFIG_IMX) += imx6_ccm.o
>>  obj-$(CONFIG_IMX) += imx6_src.o
>>  obj-$(CONFIG_IMX) += imx7_ccm.o
>>  obj-$(CONFIG_IMX) += imx2_wdt.o
>> +obj-$(CONFIG_IMX) += imx7_snvs.o
>>  obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
>>  obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
>>  obj-$(CONFIG_MAINSTONE) += mst_fpga.o
>> diff --git a/hw/misc/imx7_snvs.c b/hw/misc/imx7_snvs.c
>> new file mode 100644
>> index 00..670b9f4639
>> --- /dev/null
>> +++ b/hw/misc/imx7_snvs.c
>> @@ -0,0 +1,83 @@
>> +/*
>> + * IMX7 Secure Non-Volatile Storage
>> + *
>> + * Copyright (c) 2017, Impinj, Inc.
>> + *
>> + * Author: Andrey Smirnov 
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
>> + * See the COPYING file in the top-level directory.
>> + *
>> + * Bare minimum emulation code needed to support being able to shut
>> + * down linux guest gracefully.
>> + */
>> +
>> +#include "qemu/osdep.h"
>> +#include "hw/misc/imx7_snvs.h"
>> +#include "qemu/log.h"
>> +#include "sysemu/sysemu.h"
>> +
>> +static uint64_t imx7_snvs_read(void *opaque, hwaddr offset, unsigned size)
>> +{
>> +return 0;
>> +}
>> +
>> +static void imx7_snvs_write(void *opaque, hwaddr offset,
>> +uint64_t v, unsigned size)
>> +{
>> +const uint32_t value = v;
>> +const uint32_t mask  = SNVS_LPCR_TOP | SNVS_LPCR_DP_EN;
>> +
>> +if (offset == SNVS_LPCR && ((value & mask) == mask)) {
>> +qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>> +}
>> +}
>> +
>> +static const struct MemoryRegionOps imx7_snvs_ops = {
>> +.read = imx7_snvs_read,
>
> Same here, you can remove the imx7_snvs_read() function since
> memory_region_dispatch_read() takes care of this and return 0.
>

Hmm, I don't think I agree both from reading code and trying this out.
Without .read callback the call chain ends up being the following
memory_region_dispatch_read() -> memory_region_dispatch_read1() ->
access_with_adjusted_size(..., memory_region_oldmmio_read_accessor,
...) -> memory_region_oldmmio_read_accessor() ->
mr->ops->old_mmio.read[ctz32(size)]() -> SEGFAULT

As much as I'd love to get rid of dummy .read callback, I don't see a
way to do that, unfortunately.

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH v4 00/14] Initial i.MX7 support

2018-02-06 Thread Andrey Smirnov
On Wed, Jan 31, 2018 at 9:03 AM, Philippe Mathieu-Daudé  wrote:
> Hi Peter, Andrey.
>
> On 01/15/2018 10:36 PM, Andrey Smirnov wrote:
>> Hi everyone,
>>
>> This v4 of the patch series containing the work that I've done in
>> order to enable support for i.MX7 emulation in QEMU.
>>
>> *NOTE*: Patches 1 and 2 are provided for the sake of completness and
>>   are going to have to be adapted once Philippe's SD changes
>>   land in master. As such, they are NOT ready to be
>>   accepted/merged.
>
> Peter:
> Since my series are taking longer, if this series is ready it is
> probably easier to apply Andrey series first and I'll adapt my SDHCI
> series after.
>
> Andrey:
> I only plan to keep the sdhci.c file generic (dealing with quirks) and
> split out the imx usdhci code, similar to this patch:
> https://lists.gnu.org/archive/html/qemu-devel/2018-01/msg01265.html

Yes, I understand that, but I still am not clear how you propose
dealing with the fact that i.MX specific read/write functions need to
call similar functions from parent SDHC class. Are you planning on
adding overridable read()/write() methods to SDHCICommonClass?

Thanks,
Andrey Smirnov



Re: [Qemu-devel] [PATCH v4 09/14] pci: Add support for Designware IP block

2018-02-06 Thread Andrey Smirnov
On Wed, Jan 31, 2018 at 4:13 AM, Marcel Apfelbaum  wrote:
> On 30/01/2018 19:49, Andrey Smirnov wrote:
>> On Tue, Jan 30, 2018 at 5:18 AM, Marcel Apfelbaum
>>  wrote:
>>> Hi Andrei,
>>>
>>> Sorry for letting you wait,
>>> I have some comments/questions below.
>>>
>>>
>>> On 16/01/2018 3:37, Andrey Smirnov wrote:
>>>>
>>>> Add code needed to get a functional PCI subsytem when using in
>>>> conjunction with upstream Linux guest (4.13+). Tested to work against
>>>> "e1000e" (network adapter, using MSI interrupts) as well as
>>>> "usb-ehci" (USB controller, using legacy PCI interrupts).
>>>>
>>>> Cc: Peter Maydell 
>>>> Cc: Jason Wang 
>>>> Cc: Philippe Mathieu-Daudé 
>>>> Cc: qemu-devel@nongnu.org
>>>> Cc: qemu-...@nongnu.org
>>>> Cc: yurov...@gmail.com
>>>> Signed-off-by: Andrey Smirnov 
>>>> ---
>>>>   default-configs/arm-softmmu.mak  |   2 +
>>>>   hw/pci-host/Makefile.objs|   2 +
>>>>   hw/pci-host/designware.c | 618
>>>> +++
>>>>   include/hw/pci-host/designware.h |  93 ++
>>>>   include/hw/pci/pci_ids.h |   2 +
>>>>   5 files changed, 717 insertions(+)
>>>>   create mode 100644 hw/pci-host/designware.c
>>>>   create mode 100644 include/hw/pci-host/designware.h
>>>>
>>>> diff --git a/default-configs/arm-softmmu.mak
>>>> b/default-configs/arm-softmmu.mak
>>>> index b0d6e65038..0c5ae914ed 100644
>>>> --- a/default-configs/arm-softmmu.mak
>>>> +++ b/default-configs/arm-softmmu.mak
>>>> @@ -132,3 +132,5 @@ CONFIG_GPIO_KEY=y
>>>>   CONFIG_MSF2=y
>>>>   CONFIG_FW_CFG_DMA=y
>>>>   CONFIG_XILINX_AXI=y
>>>> +CONFIG_PCI_DESIGNWARE=y
>>>> +
>>>> diff --git a/hw/pci-host/Makefile.objs b/hw/pci-host/Makefile.objs
>>>> index 9c7909cf44..0e2c0a123b 100644
>>>> --- a/hw/pci-host/Makefile.objs
>>>> +++ b/hw/pci-host/Makefile.objs
>>>> @@ -17,3 +17,5 @@ common-obj-$(CONFIG_PCI_PIIX) += piix.o
>>>>   common-obj-$(CONFIG_PCI_Q35) += q35.o
>>>>   common-obj-$(CONFIG_PCI_GENERIC) += gpex.o
>>>>   common-obj-$(CONFIG_PCI_XILINX) += xilinx-pcie.o
>>>> +
>>>> +common-obj-$(CONFIG_PCI_DESIGNWARE) += designware.o
>>>> diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
>>>> new file mode 100644
>>>> index 00..98fff5e5f3
>>>> --- /dev/null
>>>> +++ b/hw/pci-host/designware.c
>>>> @@ -0,0 +1,618 @@
>>>> +/*
>>>> + * Copyright (c) 2017, Impinj, Inc.
>>>
>>> 2018 :)
>>>
>>>> + *
>>>> + * Designware PCIe IP block emulation
>>>> + *
>>>> + * This library is free software; you can redistribute it and/or
>>>> + * modify it under the terms of the GNU Lesser General Public
>>>> + * License as published by the Free Software Foundation; either
>>>> + * version 2 of the License, or (at your option) any later version.
>>>> + *
>>>> + * This library 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
>>>> + * Lesser General Public License for more details.
>>>> + *
>>>> + * You should have received a copy of the GNU Lesser General Public
>>>> + * License along with this library; if not, see
>>>> + * <http://www.gnu.org/licenses/>.
>>>> + */
>>>> +
>>>> +#include "qemu/osdep.h"
>>>> +#include "qapi/error.h"
>>>> +#include "hw/pci/msi.h"
>>>> +#include "hw/pci/pci_bridge.h"
>>>> +#include "hw/pci/pci_host.h"
>>>> +#include "hw/pci/pcie_port.h"
>>>> +#include "hw/pci-host/designware.h"
>>>> +
>>>> +#define PCIE_PORT_LINK_CONTROL  0x710
>>>> +
>>>> +#define PCIE_PHY_DEBUG_R1   0x72C
>>>> +#define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP  BIT(4)
>>>> +
>>>> +#define PCIE_LINK_WIDTH_SPEED_CONTROL   0x80C
>>>> +
>>>> +#define PCIE_MSI_ADDR_LO0x820
>>>> +#define PCIE

[Qemu-devel] [PATCH v5 00/14] Initial i.MX7 support

2018-02-06 Thread Andrey Smirnov
Hi everyone,

This v5 of the patch series containing the work that I've done in
order to enable support for i.MX7 emulation in QEMU.

As the one before last commit in the series states the supported i.MX7
features are:

* up to 2 Cortex A9 cores (SMP works with PSCI)
* A7 MPCORE (identical to A15 MPCORE)
* 4 GPTs modules
* 7 GPIO controllers
* 2 IOMUXC controllers
* 1 CCM module
* 1 SVNS module
* 1 SRC module
* 1 GPCv2 controller
* 4 eCSPI controllers
* 4 I2C controllers
* 7 i.MX UART controllers
* 2 FlexCAN controllers
* 2 Ethernet controllers (FEC)
* 3 SD controllers (USDHC)
* 4 WDT modules
* 1 SDMA module
* 1 GPR module
* 2 USBMISC modules
* 2 ADC modules
* 1 PCIe controller
* 3 USB controllers
* 1 LCD controller
* 1 ARMv7 DAP IP block

Feedback is welcome!

Changes since [v4]:

- Rebase patchest on top of latest QEMU master

- Reworked PCIE emulation code to create MemoryRegions
  only once

- Fixed incorrect usages of PCI instead of PCIE

- Fixed device class reported by PCIE bridge

- Added patch to make pci_data_read() and pci_data_write() usable
  for PCIE devices as well

- Converted PCIE code to use pci_data_read() and pci_data_write()

- Added VMStateDescription code for PCIE

- Collected Reviewed-by tag from Philippe

Changes since [v3]:

- Changes to FEC were split into a separate set and merged to master

- Patchest is rebased on latest master

- Converted to use PSCI DT fixup code that is shared with virt
  platform (now relocated to live in arm/boot.c)

- Large number of dummy block were converted to use
  create_unimplemented_device() as opposed to its own dedicated
  type

- Incorporated varios small feedback items

- Collected Reviewed-by tags from Peter

Changes since [v2]:

- Added stubs for more blocks that were causing memory
  transactions when booting Linux guest as were revealed by
  additional testing of the patchest

- Added proper USB emulation code, so now it should be possible to
  emulated guest's USB bus

Changes since [v1]:

- Patchset no longer relies on "ignore_memory_transaction_failures = false"
  for its functionality

- As a consequnce of implementing the above a number of patches
  implementing dummy IP block emulation as well as PCIe emulation
  patches that I alluded to in [v1] are now included in this patch
  series

- "has_el3" property is no longer being set to "false" as a part
  of intialization of A7 CPU. I couldn't reproduce the issues that
  I thought I was having, so I just dropped that code.

- A number of smaller feedback items from Peter and other has been
  incorporated into the patches.


Thanks,
Andrey Smirnov

[v4] https://lists.gnu.org/archive/html/qemu-devel/2018-01/msg03264.html
[v3] https://lists.gnu.org/archive/html/qemu-devel/2017-11/msg04236.html
[v2] https://lists.gnu.org/archive/html/qemu-devel/2017-10/msg05516.html
[v1] https://lists.gnu.org/archive/html/qemu-devel/2017-09/msg04770.html

Andrey Smirnov (14):
  sdhci: Add i.MX specific subtype of SDHCI
  hw: i.MX: Convert i.MX6 to use TYPE_IMX_USDHC
  i.MX: Add code to emulate i.MX7 CCM, PMU and ANALOG IP blocks
  i.MX: Add code to emulate i.MX2 watchdog IP block
  i.MX: Add code to emulate i.MX7 SNVS IP-block
  i.MX: Add code to emulate GPCv2 IP block
  i.MX: Add i.MX7 GPT variant
  i.MX: Add implementation of i.MX7 GPR IP block
  pci: Use pci_config_size in pci_data_* accessors
  pci: Add support for Designware IP block
  usb: Add basic code to emulate Chipidea USB IP
  i.MX: Add i.MX7 SOC implementation.
  hw/arm: Move virt's PSCI DT fixup code to arm/boot.c
  Implement support for i.MX7 Sabre board

 default-configs/arm-softmmu.mak  |   3 +
 hw/arm/Makefile.objs |   3 +
 hw/arm/boot.c|  65 
 hw/arm/fsl-imx6.c|   2 +-
 hw/arm/fsl-imx7.c| 580 ++
 hw/arm/mcimx7d-sabre.c   |  90 +
 hw/arm/virt.c|  61 
 hw/intc/Makefile.objs|   2 +-
 hw/intc/imx_gpcv2.c  | 125 +++
 hw/misc/Makefile.objs|   4 +
 hw/misc/imx2_wdt.c   |  89 +
 hw/misc/imx7_ccm.c   | 277 ++
 hw/misc/imx7_gpr.c   | 124 +++
 hw/misc/imx7_snvs.c  |  83 +
 hw/misc/trace-events |   4 +
 hw/pci-host/Makefile.objs|   2 +
 hw/pci-host/designware.c | 759 +++
 hw/pci/pci_host.c|  13 +-
 hw/sd/sdhci-internal.h   |  20 ++
 hw/sd/sdhci.c| 230 +++-
 hw/timer/imx_gpt.c   |  25 ++
 hw/usb/Makefile.objs |   1 +
 hw/usb/chipidea.c| 176 +
 include/hw/arm/fsl

[Qemu-devel] [PATCH v5 03/14] i.MX: Add code to emulate i.MX7 CCM, PMU and ANALOG IP blocks

2018-02-06 Thread Andrey Smirnov
Add minimal code needed to allow upstream Linux guest to boot.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: Marcel Apfelbaum 
Cc: Michael S. Tsirkin 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Reviewed-by: Peter Maydell 
Signed-off-by: Andrey Smirnov 
---
 hw/misc/Makefile.objs  |   1 +
 hw/misc/imx7_ccm.c | 277 +
 include/hw/misc/imx7_ccm.h | 139 +++
 3 files changed, 417 insertions(+)
 create mode 100644 hw/misc/imx7_ccm.c
 create mode 100644 include/hw/misc/imx7_ccm.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index d517f83e81..a28e5e49b0 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -33,6 +33,7 @@ obj-$(CONFIG_IMX) += imx31_ccm.o
 obj-$(CONFIG_IMX) += imx25_ccm.o
 obj-$(CONFIG_IMX) += imx6_ccm.o
 obj-$(CONFIG_IMX) += imx6_src.o
+obj-$(CONFIG_IMX) += imx7_ccm.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/imx7_ccm.c b/hw/misc/imx7_ccm.c
new file mode 100644
index 00..d90c48bfec
--- /dev/null
+++ b/hw/misc/imx7_ccm.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2018, Impinj, Inc.
+ *
+ * i.MX7 CCM, PMU and ANALOG IP blocks emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+
+#include "hw/misc/imx7_ccm.h"
+
+static void imx7_analog_reset(DeviceState *dev)
+{
+IMX7AnalogState *s = IMX7_ANALOG(dev);
+
+memset(s->pmu, 0, sizeof(s->pmu));
+memset(s->analog, 0, sizeof(s->analog));
+
+s->analog[ANALOG_PLL_ARM] = 0x2042;
+s->analog[ANALOG_PLL_DDR] = 0x0060302c;
+s->analog[ANALOG_PLL_DDR_SS]  = 0x;
+s->analog[ANALOG_PLL_DDR_NUM] = 0x06aaac4d;
+s->analog[ANALOG_PLL_DDR_DENOM]   = 0x13ec;
+s->analog[ANALOG_PLL_480] = 0x2000;
+s->analog[ANALOG_PLL_480A]= 0x52605a56;
+s->analog[ANALOG_PLL_480B]= 0x52525216;
+s->analog[ANALOG_PLL_ENET]= 0x1fc0;
+s->analog[ANALOG_PLL_AUDIO]   = 0x0001301b;
+s->analog[ANALOG_PLL_AUDIO_SS]= 0x;
+s->analog[ANALOG_PLL_AUDIO_NUM]   = 0x05f5e100;
+s->analog[ANALOG_PLL_AUDIO_DENOM] = 0x2964619c;
+s->analog[ANALOG_PLL_VIDEO]   = 0x0008201b;
+s->analog[ANALOG_PLL_VIDEO_SS]= 0x;
+s->analog[ANALOG_PLL_VIDEO_NUM]   = 0xf699;
+s->analog[ANALOG_PLL_VIDEO_DENOM] = 0x000f4240;
+s->analog[ANALOG_PLL_MISC0]   = 0x;
+
+/* all PLLs need to be locked */
+s->analog[ANALOG_PLL_ARM]   |= ANALOG_PLL_LOCK;
+s->analog[ANALOG_PLL_DDR]   |= ANALOG_PLL_LOCK;
+s->analog[ANALOG_PLL_480]   |= ANALOG_PLL_LOCK;
+s->analog[ANALOG_PLL_480A]  |= ANALOG_PLL_LOCK;
+s->analog[ANALOG_PLL_480B]  |= ANALOG_PLL_LOCK;
+s->analog[ANALOG_PLL_ENET]  |= ANALOG_PLL_LOCK;
+s->analog[ANALOG_PLL_AUDIO] |= ANALOG_PLL_LOCK;
+s->analog[ANALOG_PLL_VIDEO] |= ANALOG_PLL_LOCK;
+s->analog[ANALOG_PLL_MISC0] |= ANALOG_PLL_LOCK;
+
+/*
+ * Since I couldn't find any info about this in the reference
+ * manual the value of this register is based strictly on matching
+ * what Linux kernel expects it to be.
+ */
+s->analog[ANALOG_DIGPROG]  = 0x72;
+/*
+ * Set revision to be 1.0 (Arbitrary choice, no particular
+ * reason).
+ */
+s->analog[ANALOG_DIGPROG] |= 0x10;
+}
+
+static void imx7_ccm_reset(DeviceState *dev)
+{
+IMX7CCMState *s = IMX7_CCM(dev);
+
+memset(s->ccm, 0, sizeof(s->ccm));
+}
+
+#define CCM_INDEX(offset)   (((offset) & ~(hwaddr)0xF) / sizeof(uint32_t))
+#define CCM_BITOP(offset)   ((offset) & (hwaddr)0xF)
+
+enum {
+CCM_BITOP_NONE = 0x00,
+CCM_BITOP_SET  = 0x04,
+CCM_BITOP_CLR  = 0x08,
+CCM_BITOP_TOG  = 0x0C,
+};
+
+static uint64_t imx7_set_clr_tog_read(void *opaque, hwaddr offset,
+  unsigned size)
+{
+const uint32_t *mmio = opaque;
+
+return mmio[CCM_INDEX(offset)];
+}
+
+static void imx7_set_clr_tog_write(void *opaque, hwaddr offset,
+   uint64_t value, unsigned size)
+{
+const uint8_t  bitop = CCM_BITOP(offset);
+const uint32_t index = CCM_INDEX(offset);
+uint32_t *mmio = opaque;
+
+switch (bitop) {
+case CCM_BITOP_NONE:
+mmio[index]  = value;
+break;
+case CCM_BITOP_SET:
+mmio[index] |= value;
+break;
+case CCM_BITOP_CLR:
+mmio[index] &= ~value;
+break;
+case CCM_BITOP_TOG:
+mmio[index] ^= value;
+break;
+};
+}
+
+static const struct Me

[Qemu-devel] [PATCH v5 02/14] hw: i.MX: Convert i.MX6 to use TYPE_IMX_USDHC

2018-02-06 Thread Andrey Smirnov
Convert i.MX6 to use TYPE_IMX_USDHC since that's what real HW comes
with.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: Marcel Apfelbaum 
Cc: Michael S. Tsirkin 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Reviewed-by: Philippe Mathieu-Daudé 
Signed-off-by: Andrey Smirnov 
---
 hw/arm/fsl-imx6.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
index b0d4088290..e6559a8b12 100644
--- a/hw/arm/fsl-imx6.c
+++ b/hw/arm/fsl-imx6.c
@@ -93,7 +93,7 @@ static void fsl_imx6_init(Object *obj)
 }
 
 for (i = 0; i < FSL_IMX6_NUM_ESDHCS; i++) {
-object_initialize(&s->esdhc[i], sizeof(s->esdhc[i]), 
TYPE_SYSBUS_SDHCI);
+object_initialize(&s->esdhc[i], sizeof(s->esdhc[i]), TYPE_IMX_USDHC);
 qdev_set_parent_bus(DEVICE(&s->esdhc[i]), sysbus_get_default());
 snprintf(name, NAME_SIZE, "sdhc%d", i + 1);
 object_property_add_child(obj, name, OBJECT(&s->esdhc[i]), NULL);
-- 
2.14.3




[Qemu-devel] [PATCH v5 04/14] i.MX: Add code to emulate i.MX2 watchdog IP block

2018-02-06 Thread Andrey Smirnov
Add enough code to emulate i.MX2 watchdog IP block so it would be
possible to reboot the machine running Linux Guest.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: Marcel Apfelbaum 
Cc: Michael S. Tsirkin 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Reviewed-by: Peter Maydell 
Signed-off-by: Andrey Smirnov 
---
 hw/misc/Makefile.objs  |  1 +
 hw/misc/imx2_wdt.c | 89 ++
 include/hw/misc/imx2_wdt.h | 33 +
 3 files changed, 123 insertions(+)
 create mode 100644 hw/misc/imx2_wdt.c
 create mode 100644 include/hw/misc/imx2_wdt.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index a28e5e49b0..4b2b705a6c 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -34,6 +34,7 @@ obj-$(CONFIG_IMX) += imx25_ccm.o
 obj-$(CONFIG_IMX) += imx6_ccm.o
 obj-$(CONFIG_IMX) += imx6_src.o
 obj-$(CONFIG_IMX) += imx7_ccm.o
+obj-$(CONFIG_IMX) += imx2_wdt.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/imx2_wdt.c b/hw/misc/imx2_wdt.c
new file mode 100644
index 00..e47e442592
--- /dev/null
+++ b/hw/misc/imx2_wdt.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2018, Impinj, Inc.
+ *
+ * i.MX2 Watchdog IP block
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/bitops.h"
+#include "sysemu/watchdog.h"
+
+#include "hw/misc/imx2_wdt.h"
+
+#define IMX2_WDT_WCR_WDABIT(5)  /* -> External Reset WDOG_B */
+#define IMX2_WDT_WCR_SRSBIT(4)  /* -> Software Reset Signal */
+
+static uint64_t imx2_wdt_read(void *opaque, hwaddr addr,
+  unsigned int size)
+{
+return 0;
+}
+
+static void imx2_wdt_write(void *opaque, hwaddr addr,
+   uint64_t value, unsigned int size)
+{
+if (addr == IMX2_WDT_WCR &&
+(value & (IMX2_WDT_WCR_WDA | IMX2_WDT_WCR_SRS))) {
+watchdog_perform_action();
+}
+}
+
+static const MemoryRegionOps imx2_wdt_ops = {
+.read  = imx2_wdt_read,
+.write = imx2_wdt_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the
+ * real device but in practice there is no reason for a guest
+ * to access this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void imx2_wdt_realize(DeviceState *dev, Error **errp)
+{
+IMX2WdtState *s = IMX2_WDT(dev);
+
+memory_region_init_io(&s->mmio, OBJECT(dev),
+  &imx2_wdt_ops, s,
+  TYPE_IMX2_WDT".mmio",
+  IMX2_WDT_REG_NUM * sizeof(uint16_t));
+sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
+}
+
+static void imx2_wdt_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->realize = imx2_wdt_realize;
+set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+}
+
+static const TypeInfo imx2_wdt_info = {
+.name  = TYPE_IMX2_WDT,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(IMX2WdtState),
+.class_init= imx2_wdt_class_init,
+};
+
+static WatchdogTimerModel model = {
+.wdt_name = "imx2-watchdog",
+.wdt_description = "i.MX2 Watchdog",
+};
+
+static void imx2_wdt_register_type(void)
+{
+watchdog_add_model(&model);
+type_register_static(&imx2_wdt_info);
+}
+type_init(imx2_wdt_register_type)
diff --git a/include/hw/misc/imx2_wdt.h b/include/hw/misc/imx2_wdt.h
new file mode 100644
index 00..8afc99a10e
--- /dev/null
+++ b/include/hw/misc/imx2_wdt.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX2 Watchdog IP block
+ *
+ * Author: Andrey Smirnov 
+ *
+ * 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 IMX2_WDT_H
+#define IMX2_WDT_H
+
+#include "hw/sysbus.h"
+
+#define TYPE_IMX2_WDT "imx2.wdt"
+#define IMX2_WDT(obj) OBJECT_CHECK(IMX2WdtState, (obj), TYPE_IMX2_WDT)
+
+enum IMX2WdtRegisters {
+IMX2_WDT_WCR = 0x,
+IMX2_WDT_REG_NUM = 0x0008 / sizeof(uint16_t) + 1,
+};
+
+
+typedef struct IMX2WdtState {
+/*  */
+SysBusDevice parent_obj;
+
+MemoryRegion mmio;
+} IMX2WdtState;
+
+#endif /* IMX7_SNVS_H */
-- 
2.14.3




[Qemu-devel] [PATCH v5 01/14] sdhci: Add i.MX specific subtype of SDHCI

2018-02-06 Thread Andrey Smirnov
IP block found on several generations of i.MX family does not use
vanilla SDHCI implementation and it comes with a number of quirks.

Introduce i.MX SDHCI subtype of SDHCI block to add code necessary to
support unmodified Linux guest driver.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: Marcel Apfelbaum 
Cc: Michael S. Tsirkin 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Reviewed-by: Peter Maydell 
Signed-off-by: Andrey Smirnov 
---
 hw/sd/sdhci-internal.h |  20 +
 hw/sd/sdhci.c  | 230 -
 include/hw/sd/sdhci.h  |  13 +++
 3 files changed, 262 insertions(+), 1 deletion(-)

diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
index fc807f08f3..f91b73af59 100644
--- a/hw/sd/sdhci-internal.h
+++ b/hw/sd/sdhci-internal.h
@@ -84,12 +84,18 @@
 
 /* R/W Host control Register 0x0 */
 #define SDHC_HOSTCTL   0x28
+#define SDHC_CTRL_LED  0x01
 #define SDHC_CTRL_DMA_CHECK_MASK   0x18
 #define SDHC_CTRL_SDMA 0x00
 #define SDHC_CTRL_ADMA1_32 0x08
 #define SDHC_CTRL_ADMA2_32 0x10
 #define SDHC_CTRL_ADMA2_64 0x18
 #define SDHC_DMA_TYPE(x)   ((x) & SDHC_CTRL_DMA_CHECK_MASK)
+#define SDHC_CTRL_4BITBUS  0x02
+#define SDHC_CTRL_8BITBUS  0x20
+#define SDHC_CTRL_CDTEST_INS   0x40
+#define SDHC_CTRL_CDTEST_EN0x80
+
 
 /* R/W Power Control Register 0x0 */
 #define SDHC_PWRCON0x29
@@ -226,4 +232,18 @@ enum {
 sdhc_gap_write  = 2   /* SDHC stopped at block gap during write operation 
*/
 };
 
+extern const VMStateDescription sdhci_vmstate;
+
+
+#define ESDHC_MIX_CTRL  0x48
+#define ESDHC_VENDOR_SPEC   0xc0
+#define ESDHC_DLL_CTRL  0x60
+
+#define ESDHC_TUNING_CTRL   0xcc
+#define ESDHC_TUNE_CTRL_STATUS  0x68
+#define ESDHC_WTMK_LVL  0x44
+
+#define ESDHC_CTRL_4BITBUS  (0x1 << 1)
+#define ESDHC_CTRL_8BITBUS  (0x2 << 1)
+
 #endif
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index fac7fa5c72..7c9683b47d 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -244,7 +244,8 @@ static void sdhci_send_command(SDHCIState *s)
 }
 }
 
-if ((s->norintstsen & SDHC_NISEN_TRSCMP) &&
+if (!(s->quirks & SDHCI_QUIRK_NO_BUSY_IRQ) &&
+(s->norintstsen & SDHC_NISEN_TRSCMP) &&
 (s->cmdreg & SDHC_CMD_RESPONSE) == SDHC_CMD_RSP_WITH_BUSY) {
 s->norintsts |= SDHC_NIS_TRSCMP;
 }
@@ -1189,6 +1190,8 @@ static void sdhci_initfn(SDHCIState *s)
 
 s->insert_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 
sdhci_raise_insertion_irq, s);
 s->transfer_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, sdhci_data_transfer, 
s);
+
+s->io_ops = &sdhci_mmio_ops;
 }
 
 static void sdhci_uninitfn(SDHCIState *s)
@@ -1396,6 +1399,10 @@ static void sdhci_sysbus_realize(DeviceState *dev, Error 
** errp)
 }
 
 sysbus_init_irq(sbd, &s->irq);
+
+memory_region_init_io(&s->iomem, OBJECT(s), s->io_ops, s, "sdhci",
+SDHC_REGISTERS_MAP_SIZE);
+
 sysbus_init_mmio(sbd, &s->iomem);
 }
 
@@ -1447,11 +1454,232 @@ static const TypeInfo sdhci_bus_info = {
 .class_init = sdhci_bus_class_init,
 };
 
+static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
+{
+SDHCIState *s = SYSBUS_SDHCI(opaque);
+uint32_t ret;
+uint16_t hostctl;
+
+switch (offset) {
+default:
+return sdhci_read(opaque, offset, size);
+
+case SDHC_HOSTCTL:
+/*
+ * For a detailed explanation on the following bit
+ * manipulation code see comments in a similar part of
+ * usdhc_write()
+ */
+hostctl = SDHC_DMA_TYPE(s->hostctl) << (8 - 3);
+
+if (s->hostctl & SDHC_CTRL_8BITBUS) {
+hostctl |= ESDHC_CTRL_8BITBUS;
+}
+
+if (s->hostctl & SDHC_CTRL_4BITBUS) {
+hostctl |= ESDHC_CTRL_4BITBUS;
+}
+
+ret  = hostctl;
+ret |= (uint32_t)s->blkgap << 16;
+ret |= (uint32_t)s->wakcon << 24;
+
+break;
+
+case ESDHC_DLL_CTRL:
+case ESDHC_TUNE_CTRL_STATUS:
+case 0x6c:
+case ESDHC_TUNING_CTRL:
+case ESDHC_VENDOR_SPEC:
+case ESDHC_MIX_CTRL:
+case ESDHC_WTMK_LVL:
+ret = 0;
+break;
+}
+
+return ret;
+}
+
+static void
+usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
+{
+SDHCIState *s = SYSBUS_SDHCI(opaque);
+uint8_t hostctl;
+uint32_t value = (uint32_t)val;
+
+switch (offset) {
+case ESDHC_DLL_CTRL:
+case ESDHC_TUNE_CTRL_STATUS:
+case 0x6c:
+case ESDHC_TUNING_CTRL:
+case ESDHC_WTMK_LVL:
+case ESDHC_VENDOR_SPEC:
+  

[Qemu-devel] [PATCH v5 05/14] i.MX: Add code to emulate i.MX7 SNVS IP-block

2018-02-06 Thread Andrey Smirnov
Add code to emulate SNVS IP-block. Currently only the bits needed to
be able to emulate machine shutdown are implemented.

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: Marcel Apfelbaum 
Cc: Michael S. Tsirkin 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Reviewed-by: Peter Maydell 
Signed-off-by: Andrey Smirnov 
---
 hw/misc/Makefile.objs   |  1 +
 hw/misc/imx7_snvs.c | 83 +
 include/hw/misc/imx7_snvs.h | 35 +++
 3 files changed, 119 insertions(+)
 create mode 100644 hw/misc/imx7_snvs.c
 create mode 100644 include/hw/misc/imx7_snvs.h

diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 4b2b705a6c..019886912c 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -35,6 +35,7 @@ obj-$(CONFIG_IMX) += imx6_ccm.o
 obj-$(CONFIG_IMX) += imx6_src.o
 obj-$(CONFIG_IMX) += imx7_ccm.o
 obj-$(CONFIG_IMX) += imx2_wdt.o
+obj-$(CONFIG_IMX) += imx7_snvs.o
 obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
 obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
 obj-$(CONFIG_MAINSTONE) += mst_fpga.o
diff --git a/hw/misc/imx7_snvs.c b/hw/misc/imx7_snvs.c
new file mode 100644
index 00..4df482b282
--- /dev/null
+++ b/hw/misc/imx7_snvs.c
@@ -0,0 +1,83 @@
+/*
+ * IMX7 Secure Non-Volatile Storage
+ *
+ * Copyright (c) 2018, Impinj, Inc.
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * Bare minimum emulation code needed to support being able to shut
+ * down linux guest gracefully.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/misc/imx7_snvs.h"
+#include "qemu/log.h"
+#include "sysemu/sysemu.h"
+
+static uint64_t imx7_snvs_read(void *opaque, hwaddr offset, unsigned size)
+{
+return 0;
+}
+
+static void imx7_snvs_write(void *opaque, hwaddr offset,
+uint64_t v, unsigned size)
+{
+const uint32_t value = v;
+const uint32_t mask  = SNVS_LPCR_TOP | SNVS_LPCR_DP_EN;
+
+if (offset == SNVS_LPCR && ((value & mask) == mask)) {
+qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+}
+}
+
+static const struct MemoryRegionOps imx7_snvs_ops = {
+.read = imx7_snvs_read,
+.write = imx7_snvs_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void imx7_snvs_init(Object *obj)
+{
+SysBusDevice *sd = SYS_BUS_DEVICE(obj);
+IMX7SNVSState *s = IMX7_SNVS(obj);
+
+memory_region_init_io(&s->mmio, obj, &imx7_snvs_ops, s,
+  TYPE_IMX7_SNVS, 0x1000);
+
+sysbus_init_mmio(sd, &s->mmio);
+}
+
+static void imx7_snvs_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+
+dc->desc  = "i.MX7 Secure Non-Volatile Storage Module";
+}
+
+static const TypeInfo imx7_snvs_info = {
+.name  = TYPE_IMX7_SNVS,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(IMX7SNVSState),
+.instance_init = imx7_snvs_init,
+.class_init= imx7_snvs_class_init,
+};
+
+static void imx7_snvs_register_type(void)
+{
+type_register_static(&imx7_snvs_info);
+}
+type_init(imx7_snvs_register_type)
diff --git a/include/hw/misc/imx7_snvs.h b/include/hw/misc/imx7_snvs.h
new file mode 100644
index 00..255f8f26f9
--- /dev/null
+++ b/include/hw/misc/imx7_snvs.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 SNVS block emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * 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 IMX7_SNVS_H
+#define IMX7_SNVS_H
+
+#include "qemu/bitops.h"
+#include "hw/sysbus.h"
+
+
+enum IMX7SNVSRegisters {
+SNVS_LPCR = 0x38,
+SNVS_LPCR_TOP   = BIT(6),
+SNVS_LPCR_DP_EN = BIT(5)
+};
+
+#define TYPE_IMX7_SNVS "imx7.snvs"
+#define IMX7_SNVS(obj) OBJECT_CHECK(IMX7SNVSState, (obj), TYPE_IMX7_SNVS)
+
+typedef struct IMX7SNVSState {
+/*  */
+SysBusDevice parent_obj;
+
+MemoryRegion mmio;
+} IMX7SNVSState;
+
+#endif /* IMX7_SNVS_H */
-- 
2.14.3




[Qemu-devel] [PATCH v5 11/14] usb: Add basic code to emulate Chipidea USB IP

2018-02-06 Thread Andrey Smirnov
Add code to emulate Chipidea USB IP (used in i.MX SoCs). Tested to
work against:

-usb -drive if=none,id=stick,file=usb.img,format=raw -device \
 usb-storage,bus=usb-bus.0,drive=stick

Cc: Peter Maydell 
Cc: Jason Wang 
Cc: Philippe Mathieu-Daudé 
Cc: Marcel Apfelbaum 
Cc: Michael S. Tsirkin 
Cc: qemu-devel@nongnu.org
Cc: qemu-...@nongnu.org
Cc: yurov...@gmail.com
Reviewed-by: Peter Maydell 
Signed-off-by: Andrey Smirnov 
---
 hw/usb/Makefile.objs  |   1 +
 hw/usb/chipidea.c | 176 ++
 include/hw/usb/chipidea.h |  16 +
 3 files changed, 193 insertions(+)
 create mode 100644 hw/usb/chipidea.c
 create mode 100644 include/hw/usb/chipidea.h

diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
index fbcd498c59..41be700812 100644
--- a/hw/usb/Makefile.objs
+++ b/hw/usb/Makefile.objs
@@ -12,6 +12,7 @@ common-obj-$(CONFIG_USB_XHCI_NEC) += hcd-xhci-nec.o
 common-obj-$(CONFIG_USB_MUSB) += hcd-musb.o
 
 obj-$(CONFIG_TUSB6010) += tusb6010.o
+obj-$(CONFIG_IMX)  += chipidea.o
 
 # emulated usb devices
 common-obj-$(CONFIG_USB) += dev-hub.o
diff --git a/hw/usb/chipidea.c b/hw/usb/chipidea.c
new file mode 100644
index 00..60d67f88b8
--- /dev/null
+++ b/hw/usb/chipidea.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2018, Impinj, Inc.
+ *
+ * Chipidea USB block emulation code
+ *
+ * Author: Andrey Smirnov 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/usb/hcd-ehci.h"
+#include "hw/usb/chipidea.h"
+#include "qemu/log.h"
+
+enum {
+CHIPIDEA_USBx_DCIVERSION   = 0x000,
+CHIPIDEA_USBx_DCCPARAMS= 0x004,
+CHIPIDEA_USBx_DCCPARAMS_HC = BIT(8),
+};
+
+static uint64_t chipidea_read(void *opaque, hwaddr offset,
+   unsigned size)
+{
+return 0;
+}
+
+static void chipidea_write(void *opaque, hwaddr offset,
+uint64_t value, unsigned size)
+{
+}
+
+static const struct MemoryRegionOps chipidea_ops = {
+.read = chipidea_read,
+.write = chipidea_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the
+ * real device but in practice there is no reason for a guest
+ * to access this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static uint64_t chipidea_dc_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+switch (offset) {
+case CHIPIDEA_USBx_DCIVERSION:
+return 0x1;
+case CHIPIDEA_USBx_DCCPARAMS:
+/*
+ * Real hardware (at least i.MX7) will also report the
+ * controller as "Device Capable" (and 8 supported endpoints),
+ * but there doesn't seem to be much point in doing so, since
+ * we don't emulate that part.
+ */
+return CHIPIDEA_USBx_DCCPARAMS_HC;
+}
+
+return 0;
+}
+
+static void chipidea_dc_write(void *opaque, hwaddr offset,
+  uint64_t value, unsigned size)
+{
+}
+
+static const struct MemoryRegionOps chipidea_dc_ops = {
+.read = chipidea_dc_read,
+.write = chipidea_dc_write,
+.endianness = DEVICE_NATIVE_ENDIAN,
+.impl = {
+/*
+ * Our device would not work correctly if the guest was doing
+ * unaligned access. This might not be a limitation on the real
+ * device but in practice there is no reason for a guest to access
+ * this device unaligned.
+ */
+.min_access_size = 4,
+.max_access_size = 4,
+.unaligned = false,
+},
+};
+
+static void chipidea_init(Object *obj)
+{
+EHCIState *ehci = &SYS_BUS_EHCI(obj)->ehci;
+ChipideaState *ci = CHIPIDEA(obj);
+int i;
+
+for (i = 0; i < ARRAY_SIZE(ci->iomem); i++) {
+const struct {
+const char *name;
+hwaddr offset;
+uint64_t size;
+const struct MemoryRegionOps *ops;
+} regions[ARRAY_SIZE(ci->iomem)] = {
+/*
+ * Registers located between offsets 0x000 and 0xFC
+ */
+{
+.name   = TYPE_CHIPIDEA ".misc",
+.offset = 0x000,
+.size   = 0x100,
+.ops= &chipidea_ops,
+},
+/*
+ * Registers located between offsets 0x1A4 and 0x1DC
+ */
+{
+.name   = TYPE_CHIPIDEA ".endpoints",
+.offset = 0x1A4,
+.size   = 0x1DC - 0x1A4 + 4,
+.ops= &chipidea_ops,
+},
+/*
+ * USB_x_DCIV

  1   2   3   >