|
[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 |