qemu: get reg and irq from devicetree node rather than macro

fdt address is at 0x4000000, so it needs to be reserved at ld script.

Signed-off-by: liaoao <liaoao@xiaomi.com>
This commit is contained in:
liaoao
2023-08-22 19:25:33 +08:00
committed by Xiang Xiao
parent b9fb9bea1d
commit a2b9cbffc2
10 changed files with 280 additions and 31 deletions
@@ -25,7 +25,7 @@ PHDRS
}
SECTIONS
{
. = 0x40000000;
. = 0x40101000;
.text : {
_stext = .; /* Text section */
*(.vectors)
+2
View File
@@ -26,4 +26,6 @@ ifeq ($(CONFIG_BOARDCTL),y)
CSRCS += qemu_appinit.c
endif
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)fdt$(DELIM)dtc$(DELIM)libfdt
include $(TOPDIR)/boards/Board.mk
+130 -15
View File
@@ -29,6 +29,8 @@
#include <nuttx/fs/fs.h>
#include <nuttx/virtio/virtio-mmio.h>
#include <nuttx/fdt.h>
#include <libfdt.h>
#include "qemu-armv7a.h"
@@ -36,32 +38,145 @@
* Pre-processor Definitions
****************************************************************************/
#define QEMU_VIRTIO_MMIO_BASE 0x0a000000
#define QEMU_VIRTIO_MMIO_REGSIZE 0x200
#define QEMU_VIRTIO_MMIO_IRQ 48
#define QEMU_VIRTIO_MMIO_NUM 32
#define QEMU_SPI_IRQ_BASE 32
/****************************************************************************
* Private Functions
****************************************************************************/
#if defined(CONFIG_LIBC_FDT) && defined(CONFIG_DEVICE_TREE)
/****************************************************************************
* Name: qemu_virtio_register_mmio_devices
* Name: fdt_get_irq
*
* Description:
* Only can be use when the corresponding node's parent interrupt
* controller is intc node.
*
****************************************************************************/
#ifdef CONFIG_DRIVERS_VIRTIO_MMIO
static void qemu_virtio_register_mmio_devices(void)
static int unused_code
fdt_get_irq(const void *fdt, int offset)
{
uintptr_t virtio = (uintptr_t)QEMU_VIRTIO_MMIO_BASE;
size_t size = QEMU_VIRTIO_MMIO_REGSIZE;
int irq = QEMU_VIRTIO_MMIO_IRQ;
int i;
const fdt32_t *pv;
int irq = -ENOENT;
for (i = 0; i < QEMU_VIRTIO_MMIO_NUM; i++)
pv = fdt_getprop(fdt, offset, "interrupts", NULL);
if (pv != NULL)
{
virtio_register_mmio_device((void *)(virtio + size * i), irq + i);
irq = fdt32_ld(pv + 1) + QEMU_SPI_IRQ_BASE;
}
return irq;
}
/****************************************************************************
* Name: fdt_get_irq_by_path
*
* Description:
* Only can be use when the corresponding node's parent interrupt
* controller is intc node.
*
****************************************************************************/
static int unused_code
fdt_get_irq_by_path(const void *fdt, const char *path)
{
return fdt_get_irq(fdt, fdt_path_offset(fdt, path));
}
/****************************************************************************
* Name: fdt_get_reg_base
****************************************************************************/
static uintptr_t unused_code
fdt_get_reg_base(const void *fdt, int offset)
{
const void *reg;
uintptr_t addr = 0;
int parentoff;
parentoff = fdt_parent_offset(fdt, offset);
if (parentoff < 0)
{
return addr;
}
reg = fdt_getprop(fdt, offset, "reg", NULL);
if (reg != NULL)
{
if (fdt_address_cells(fdt, parentoff) == 2)
{
addr = fdt64_ld(reg);
}
else
{
addr = fdt32_ld(reg);
}
}
return addr;
}
/****************************************************************************
* Name: fdt_get_reg_base_by_path
****************************************************************************/
static uintptr_t unused_code
fdt_get_reg_base_by_path(const void *fdt, const char *path)
{
return fdt_get_reg_base(fdt, fdt_path_offset(fdt, path));
}
#ifdef CONFIG_DRIVERS_VIRTIO_MMIO
/****************************************************************************
* Name: register_virtio_devices_from_fdt
****************************************************************************/
static void register_virtio_devices_from_fdt(const void *fdt)
{
uintptr_t addr;
int offset = -1;
int irqnum;
for (; ; )
{
offset = fdt_node_offset_by_compatible(fdt, offset, "virtio,mmio");
if (offset == -FDT_ERR_NOTFOUND)
{
break;
}
addr = fdt_get_reg_base(fdt, offset);
irqnum = fdt_get_irq(fdt, offset);
if (addr > 0 && irqnum >= 0)
{
virtio_register_mmio_device((FAR void *)addr, irqnum);
}
}
}
#endif
/****************************************************************************
* Name: register_devices_from_fdt
****************************************************************************/
static void register_devices_from_fdt(void)
{
const void *fdt = fdt_get();
if (fdt == NULL)
{
return;
}
#ifdef CONFIG_DRIVERS_VIRTIO_MMIO
register_virtio_devices_from_fdt(fdt);
#endif
}
#endif
/****************************************************************************
@@ -90,8 +205,8 @@ int qemu_bringup(void)
}
#endif
#ifdef CONFIG_DRIVERS_VIRTIO_MMIO
qemu_virtio_register_mmio_devices();
#if defined(CONFIG_LIBC_FDT) && defined(CONFIG_DEVICE_TREE)
register_devices_from_fdt();
#endif
UNUSED(ret);
@@ -20,6 +20,7 @@ CONFIG_BUILTIN=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEFAULT_TASK_STACKSIZE=8192
CONFIG_DEVICE_TREE=y
CONFIG_DEV_ZERO=y
CONFIG_DRIVERS_VIDEO=y
CONFIG_DRIVERS_VIRTIO=y
@@ -44,6 +45,7 @@ CONFIG_IOB_BUFSIZE=1534
CONFIG_IOB_NBUFFERS=64
CONFIG_IOB_NCHAINS=64
CONFIG_IOB_THROTTLE=8
CONFIG_LIBC_FDT=y
CONFIG_MM_IOB=y
CONFIG_NSH_ARCHINIT=y
CONFIG_NSH_BUILTIN_APPS=y
@@ -67,6 +69,7 @@ CONFIG_START_MONTH=11
CONFIG_START_YEAR=2022
CONFIG_SYMTAB_ORDEREDBYNAME=y
CONFIG_SYSLOG_TIMESTAMP=y
CONFIG_SYSTEM_FDTDUMP=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_SYSTEM=y
CONFIG_SYSTEM_TIME64=y
@@ -20,6 +20,7 @@ CONFIG_CODECS_HASH_MD5=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEFAULT_TASK_STACKSIZE=8192
CONFIG_DEVICE_TREE=y
CONFIG_DEV_ZERO=y
CONFIG_DRIVERS_VIRTIO=y
CONFIG_DRIVERS_VIRTIO_BLK=y
@@ -42,6 +43,7 @@ CONFIG_IOB_ALIGNMENT=16
CONFIG_IOB_BUFSIZE=1534
CONFIG_IOB_NBUFFERS=64
CONFIG_IOB_THROTTLE=8
CONFIG_LIBC_FDT=y
CONFIG_NET=y
CONFIG_NETDB_DNSCLIENT=y
CONFIG_NETDB_DNSCLIENT_ENTRIES=4
@@ -89,6 +91,7 @@ CONFIG_START_YEAR=2022
CONFIG_SYMTAB_ORDEREDBYNAME=y
CONFIG_SYSLOG_TIMESTAMP=y
CONFIG_SYSTEM_DHCPC_RENEW=y
CONFIG_SYSTEM_FDTDUMP=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_PING=y
CONFIG_SYSTEM_SYSTEM=y
@@ -21,6 +21,7 @@ CONFIG_CODECS_HASH_MD5=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEFAULT_TASK_STACKSIZE=8192
CONFIG_DEVICE_TREE=y
CONFIG_DEV_ZERO=y
CONFIG_DRIVERS_VIRTIO=y
CONFIG_DRIVERS_VIRTIO_BLK=y
@@ -43,6 +44,7 @@ CONFIG_IOB_ALIGNMENT=16
CONFIG_IOB_BUFSIZE=1534
CONFIG_IOB_NBUFFERS=64
CONFIG_IOB_THROTTLE=8
CONFIG_LIBC_FDT=y
CONFIG_NET=y
CONFIG_NETDB_DNSCLIENT=y
CONFIG_NETDB_DNSCLIENT_ENTRIES=4
@@ -90,6 +92,7 @@ CONFIG_START_YEAR=2022
CONFIG_SYMTAB_ORDEREDBYNAME=y
CONFIG_SYSLOG_TIMESTAMP=y
CONFIG_SYSTEM_DHCPC_RENEW=y
CONFIG_SYSTEM_FDTDUMP=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_PING=y
CONFIG_SYSTEM_SYSTEM=y
@@ -19,6 +19,7 @@ CONFIG_CODECS_HASH_MD5=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEFAULT_TASK_STACKSIZE=8192
CONFIG_DEVICE_TREE=y
CONFIG_DEV_ZERO=y
CONFIG_DRIVERS_VIRTIO=y
CONFIG_DRIVERS_VIRTIO_BLK=y
@@ -40,6 +41,7 @@ CONFIG_INTELHEX_BINARY=y
CONFIG_IOB_BUFSIZE=1534
CONFIG_IOB_NBUFFERS=64
CONFIG_IOB_THROTTLE=8
CONFIG_LIBC_FDT=y
CONFIG_NET=y
CONFIG_NETDB_DNSCLIENT=y
CONFIG_NETDB_DNSCLIENT_ENTRIES=4
@@ -88,6 +90,7 @@ CONFIG_START_YEAR=2022
CONFIG_SYMTAB_ORDEREDBYNAME=y
CONFIG_SYSLOG_TIMESTAMP=y
CONFIG_SYSTEM_DHCPC_RENEW=y
CONFIG_SYSTEM_FDTDUMP=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_PING=y
CONFIG_SYSTEM_SYSTEM=y
@@ -21,6 +21,7 @@ CONFIG_CODECS_HASH_MD5=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_DEFAULT_TASK_STACKSIZE=8192
CONFIG_DEVICE_TREE=y
CONFIG_DEV_ZERO=y
CONFIG_DRIVERS_VIRTIO=y
CONFIG_DRIVERS_VIRTIO_BLK=y
@@ -41,6 +42,7 @@ CONFIG_INTELHEX_BINARY=y
CONFIG_IOB_BUFSIZE=1534
CONFIG_IOB_NBUFFERS=64
CONFIG_IOB_THROTTLE=8
CONFIG_LIBC_FDT=y
CONFIG_NET=y
CONFIG_NETDB_DNSCLIENT=y
CONFIG_NETDB_DNSCLIENT_ENTRIES=4
@@ -89,6 +91,7 @@ CONFIG_START_YEAR=2022
CONFIG_SYMTAB_ORDEREDBYNAME=y
CONFIG_SYSLOG_TIMESTAMP=y
CONFIG_SYSTEM_DHCPC_RENEW=y
CONFIG_SYSTEM_FDTDUMP=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_PING=y
CONFIG_SYSTEM_SYSTEM=y
@@ -26,4 +26,6 @@ ifeq ($(CONFIG_BOARDCTL),y)
CSRCS += qemu_appinit.c
endif
CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)libs$(DELIM)libc$(DELIM)fdt$(DELIM)dtc$(DELIM)libfdt
include $(TOPDIR)/boards/Board.mk
+130 -15
View File
@@ -29,6 +29,8 @@
#include <nuttx/fs/fs.h>
#include <nuttx/virtio/virtio-mmio.h>
#include <nuttx/fdt.h>
#include <libfdt.h>
#include "qemu-armv8a.h"
@@ -36,32 +38,145 @@
* Pre-processor Definitions
****************************************************************************/
#define QEMU_VIRTIO_MMIO_BASE 0x0a000000
#define QEMU_VIRTIO_MMIO_REGSIZE 0x200
#define QEMU_VIRTIO_MMIO_IRQ 48
#define QEMU_VIRTIO_MMIO_NUM 32
#define QEMU_SPI_IRQ_BASE 32
/****************************************************************************
* Private Functions
****************************************************************************/
#if defined(CONFIG_LIBC_FDT) && defined(CONFIG_DEVICE_TREE)
/****************************************************************************
* Name: qemu_virtio_register_mmio_devices
* Name: fdt_get_irq
*
* Description:
* Only can be use when the corresponding node's parent interrupt
* controller is intc node.
*
****************************************************************************/
#ifdef CONFIG_DRIVERS_VIRTIO_MMIO
static void qemu_virtio_register_mmio_devices(void)
static int unused_code
fdt_get_irq(const void *fdt, int offset)
{
uintptr_t virtio = (uintptr_t)QEMU_VIRTIO_MMIO_BASE;
size_t size = QEMU_VIRTIO_MMIO_REGSIZE;
int irq = QEMU_VIRTIO_MMIO_IRQ;
int i;
const fdt32_t *pv;
int irq = -ENOENT;
for (i = 0; i < QEMU_VIRTIO_MMIO_NUM; i++)
pv = fdt_getprop(fdt, offset, "interrupts", NULL);
if (pv != NULL)
{
virtio_register_mmio_device((FAR void *)(virtio + size * i), irq + i);
irq = fdt32_ld(pv + 1) + QEMU_SPI_IRQ_BASE;
}
return irq;
}
/****************************************************************************
* Name: fdt_get_irq_by_path
*
* Description:
* Only can be use when the corresponding node's parent interrupt
* controller is intc node.
*
****************************************************************************/
static int unused_code
fdt_get_irq_by_path(const void *fdt, const char *path)
{
return fdt_get_irq(fdt, fdt_path_offset(fdt, path));
}
/****************************************************************************
* Name: fdt_get_reg_base
****************************************************************************/
static uintptr_t unused_code
fdt_get_reg_base(const void *fdt, int offset)
{
const void *reg;
uintptr_t addr = 0;
int parentoff;
parentoff = fdt_parent_offset(fdt, offset);
if (parentoff < 0)
{
return addr;
}
reg = fdt_getprop(fdt, offset, "reg", NULL);
if (reg != NULL)
{
if (fdt_address_cells(fdt, parentoff) == 2)
{
addr = fdt64_ld(reg);
}
else
{
addr = fdt32_ld(reg);
}
}
return addr;
}
/****************************************************************************
* Name: fdt_get_reg_base_by_path
****************************************************************************/
static uintptr_t unused_code
fdt_get_reg_base_by_path(const void *fdt, const char *path)
{
return fdt_get_reg_base(fdt, fdt_path_offset(fdt, path));
}
#ifdef CONFIG_DRIVERS_VIRTIO_MMIO
/****************************************************************************
* Name: register_virtio_devices_from_fdt
****************************************************************************/
static void register_virtio_devices_from_fdt(const void *fdt)
{
uintptr_t addr;
int offset = -1;
int irqnum;
for (; ; )
{
offset = fdt_node_offset_by_compatible(fdt, offset, "virtio,mmio");
if (offset == -FDT_ERR_NOTFOUND)
{
break;
}
addr = fdt_get_reg_base(fdt, offset);
irqnum = fdt_get_irq(fdt, offset);
if (addr > 0 && irqnum >= 0)
{
virtio_register_mmio_device((FAR void *)addr, irqnum);
}
}
}
#endif
/****************************************************************************
* Name: register_devices_from_fdt
****************************************************************************/
static void register_devices_from_fdt(void)
{
const void *fdt = fdt_get();
if (fdt == NULL)
{
return;
}
#ifdef CONFIG_DRIVERS_VIRTIO_MMIO
register_virtio_devices_from_fdt(fdt);
#endif
}
#endif
/****************************************************************************
@@ -90,8 +205,8 @@ int qemu_bringup(void)
}
#endif
#ifdef CONFIG_DRIVERS_VIRTIO_MMIO
qemu_virtio_register_mmio_devices();
#if defined(CONFIG_LIBC_FDT) && defined(CONFIG_DEVICE_TREE)
register_devices_from_fdt();
#endif
UNUSED(ret);