[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [UNIKRAFT PATCH RFCv2 12/27] plat/platform_bus: Add probe/match interface for platform devices
There is no hardware ID for platform device on arm64 device-tree, thus it introduces an ID match interface to identify the device id. device id should be registered as a constant value. Also it introduces probe interface to parse the neccessary resource (irq, base/size) in device-tree. Signed-off-by: Jia He <justin.he@xxxxxxx> --- plat/common/include/platform_bus.h | 26 ++++- plat/common/platform_bus.c | 148 +++++++++++++++-------------- 2 files changed, 96 insertions(+), 78 deletions(-) diff --git a/plat/common/include/platform_bus.h b/plat/common/include/platform_bus.h index efc21a0..ad56e0e 100644 --- a/plat/common/include/platform_bus.h +++ b/plat/common/include/platform_bus.h @@ -43,8 +43,10 @@ * table of these IDs for each device that it supports. */ #define PLATFORM_DEVICE_ID_START (0x100) -#define VIRTIO_MMIO_ID PLATFORM_DEVICE_ID_START -#define PLATFORM_DEVICE_ID_END (PLATFORM_DEVICE_ID_START + 0x100) +#define VIRTIO_MMIO_ID (PLATFORM_DEVICE_ID_START) +#define GEN_PCI_ID (PLATFORM_DEVICE_ID_START + 1) + +#define PLATFORM_DEVICE_ID_END (GEN_PCI_ID + 1) #define UK_MAX_VIRTIO_MMIO_DEVICE (0x2) @@ -52,16 +54,25 @@ struct pf_device_id { uint16_t device_id; }; +struct device_match_table { + const char *compatible; + struct pf_device_id *id; +}; + struct pf_device; -typedef int (*pf_driver_add_func_t)(struct pf_device *); typedef int (*pf_driver_init_func_t)(struct uk_alloc *a); +typedef int (*pf_driver_add_func_t)(struct pf_device *); +typedef int (*pf_driver_probe_func_t)(struct pf_device *); +typedef int (*pf_driver_match_func_t)(const char *); struct pf_driver { UK_TAILQ_ENTRY(struct pf_driver) next; const struct pf_device_id *device_ids; pf_driver_init_func_t init; /* optional */ + pf_driver_probe_func_t probe; pf_driver_add_func_t add_dev; + pf_driver_match_func_t match; }; UK_TAILQ_HEAD(pf_driver_list, struct pf_driver); @@ -76,6 +87,7 @@ struct pf_device { struct pf_driver *drv; enum pf_device_state state; + int fdt_offset; /* The start offset of fdt node for device */ uint64_t base; unsigned long irq; }; @@ -87,12 +99,16 @@ UK_TAILQ_HEAD(pf_device_list, struct pf_device); #define _PF_REGFNNAME(x, y) x##y +#define PF_REGISTER_CTOR(CTOR) \ + UK_CTOR_FUNC(1, CTOR) + #define _PF_REGISTER_DRIVER(libname, b) \ - static void __constructor_prio(105) \ + static void \ _PF_REGFNNAME(libname, _pf_register_driver)(void) \ { \ _pf_register_driver((b)); \ - } + } \ + PF_REGISTER_CTOR(_PF_REGFNNAME(libname, _pf_register_driver)) /* Do not use this function directly: */ void _pf_register_driver(struct pf_driver *drv); diff --git a/plat/common/platform_bus.c b/plat/common/platform_bus.c index 1410e71..fecb389 100644 --- a/plat/common/platform_bus.c +++ b/plat/common/platform_bus.c @@ -52,8 +52,10 @@ struct pf_bus_handler { }; static struct pf_bus_handler pfh; -static const char * const pf_device_list[] = { +static const char *pf_device_compatilbe_list[] = { "virtio,mmio", + "pci-host-ecam-generic", + NULL }; static inline int pf_device_id_match(const struct pf_device_id *id0, @@ -67,14 +69,22 @@ static inline int pf_device_id_match(const struct pf_device_id *id0, return rc; } -static inline struct pf_driver *pf_find_driver(struct pf_device_id *id) +static inline struct pf_driver *pf_find_driver(const char *compatible) { struct pf_driver *drv; + struct pf_device_id id; UK_TAILQ_FOREACH(drv, &pfh.drv_list, next) { - if (pf_device_id_match(id, drv->device_ids)) { - uk_pr_debug("pf driver found devid=%d\n", drv->device_ids->device_id); - return drv; /* driver found */ + if (!drv->match) + continue; + + id.device_id = (uint16_t)drv->match(compatible); + if (id.device_id) { + if (pf_device_id_match(&id, drv->device_ids)) { + uk_pr_debug("pf driver found devid(0x%x)\n", id.device_id); + + return drv; + } } } @@ -84,104 +94,96 @@ static inline struct pf_driver *pf_find_driver(struct pf_device_id *id) } static inline int pf_driver_add_device(struct pf_driver *drv, - struct pf_device_id *devid, - __u64 dev_base, - int dev_irq) + struct pf_device *dev) { - struct pf_device *dev; int ret; UK_ASSERT(drv != NULL); UK_ASSERT(drv->add_dev != NULL); + UK_ASSERT(dev != NULL); - dev = (struct pf_device *) uk_calloc(pfh.a, 1, sizeof(*dev)); - if (!dev) { - uk_pr_err("Platform : Failed to initialize: Out of memory!\n"); - return -ENOMEM; - } - - memcpy(&dev->id, devid, sizeof(dev->id)); - uk_pr_debug("pf_driver_add_device dev->id=%d\n", dev->id.device_id); - - dev->base = dev_base; - dev->irq = dev_irq; + uk_pr_debug("pf_driver_add_device devid=%d\n", dev->id.device_id); ret = drv->add_dev(dev); if (ret < 0) { uk_pr_err("Platform Failed to initialize device driver\n"); - uk_free(pfh.a, dev); } return ret; } +static inline int pf_driver_probe_device(struct pf_driver *drv, + struct pf_device *dev) +{ + int ret; + + UK_ASSERT(drv != NULL && dev != NULL); + UK_ASSERT(drv->probe != NULL); + + uk_pr_info("pf_driver_probe_device devid=%d\n", dev->id.device_id); + + ret = drv->probe(dev); + if (ret < 0) { + uk_pr_err("Platform Failed to probe device driver\n"); + + return ret; + } + + return 0; +} + static int pf_probe(void) { - struct pf_device_id devid; struct pf_driver *drv; - int i; - int end_offset = -1; + int idx = 0; int ret = -ENODEV; - const fdt32_t *prop; - int type, hwirq, prop_len; - __u64 reg_base; - __phys_addr dev_base; - int dev_irq; + struct pf_device *dev; + int fdt_pf = -1; uk_pr_info("Probe PF\n"); - /* We only support virtio_mmio as a platform device here. - * A loop here is needed for finding drivers if more devices - */ - devid.device_id = VIRTIO_MMIO_ID; + /* Search all the platform bus devices provided by fdt */ + do { + fdt_pf = fdt_node_offset_idx_by_compatible_list(_libkvmplat_cfg.dtb, + fdt_pf, pf_device_compatilbe_list, &idx); + if (fdt_pf < 0) { + uk_pr_info("End of searching platform devices\n"); + break; + } - drv = pf_find_driver(&devid); - if (!drv) { - uk_pr_info("<no driver>\n"); - return -ENODEV; - } + /* Alloc dev */ + dev = (struct pf_device *) uk_calloc(pfh.a, 1, sizeof(*dev)); + if (!dev) { + uk_pr_err("Platform : Failed to initialize: Out of memory!\n"); + return -ENOMEM; + } - uk_pr_info("driver %p\n", drv); - - /* qemu creates virtio devices in reverse order */ - for (i = 0; i < UK_MAX_VIRTIO_MMIO_DEVICE; i++) { - end_offset = fdt_node_offset_by_compatible_list(fdt_start, - end_offset, - pf_device_list); - if (end_offset == -FDT_ERR_NOTFOUND) { - uk_pr_info("device not found in fdt\n"); - goto error_exit; - } else { - prop = fdt_getprop(fdt_start, end_offset, "interrupts", &prop_len); - if (!prop) { - uk_pr_err("irq of device not found in fdt\n"); - goto error_exit; - } + dev->fdt_offset = fdt_pf; - type = fdt32_to_cpu(prop[0]); - hwirq = fdt32_to_cpu(prop[1]); + /* Find drv with compatible-id match table */ + drv = pf_find_driver(pf_device_compatilbe_list[idx]); + if (!drv) { + uk_free(pfh.a, dev); + continue; + } - prop = fdt_getprop(fdt_start, end_offset, "reg", &prop_len); - if (!prop) { - uk_pr_err("reg of device not found in fdt\n"); - goto error_exit; - } + dev->id = *(struct pf_device_id *)drv->device_ids; + uk_pr_info("driver %p\n", drv); - /* only care about base addr, ignore the size */ - reg_base = fdt32_to_cpu(prop[0]); - reg_base = reg_base << 32 | fdt32_to_cpu(prop[1]); + ret = pf_driver_probe_device(drv, dev); + if (ret < 0) { + uk_free(pfh.a, dev); + continue; } - dev_base = reg_base; - dev_irq = gic_irq_translate(type, hwirq); - - ret = pf_driver_add_device(drv, &devid, dev_base, dev_irq); - } + ret = pf_driver_add_device(drv, dev); + if (ret < 0) { + uk_pr_err("Platform Failed to initialize device driver, ret(%d)\n",ret); + uk_free(pfh.a, dev); + } + } while (1); return ret; - -error_exit: - return -ENODEV; } @@ -232,4 +234,4 @@ static struct pf_bus_handler pfh = { .b.init = pf_init, .b.probe = pf_probe }; -UK_BUS_REGISTER(&pfh.b); +UK_BUS_REGISTER_PRIORITY(&pfh.b, 1); -- 2.17.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |