// SPDX-License-Identifier: GPL-2.0 /* * vchiq_device.c - VCHIQ generic device and bus-type * * Copyright (c) 2023 Ideas On Board Oy */ #include #include #include #include #include #include "vchiq_bus.h" static int vchiq_bus_type_match(struct device *dev, struct device_driver *drv) { if (dev->bus == &vchiq_bus_type && strcmp(dev_name(dev), drv->name) == 0) return true; return false; } static int vchiq_bus_uevent(const struct device *dev, struct kobj_uevent_env *env) { const struct vchiq_device *device = container_of_const(dev, struct vchiq_device, dev); return add_uevent_var(env, "MODALIAS=vchiq:%s", dev_name(&device->dev)); } static int vchiq_bus_probe(struct device *dev) { struct vchiq_device *device = to_vchiq_device(dev); struct vchiq_driver *driver = to_vchiq_driver(dev->driver); return driver->probe(device); } const struct bus_type vchiq_bus_type = { .name = "vchiq-bus", .match = vchiq_bus_type_match, .uevent = vchiq_bus_uevent, .probe = vchiq_bus_probe, }; static void vchiq_device_release(struct device *dev) { struct vchiq_device *device = to_vchiq_device(dev); kfree(device); } struct vchiq_device * vchiq_device_register(struct device *parent, const char *name) { struct vchiq_device *device; int ret; device = kzalloc(sizeof(*device), GFP_KERNEL); if (!device) return NULL; device->dev.init_name = name; device->dev.parent = parent; device->dev.bus = &vchiq_bus_type; device->dev.dma_mask = &device->dev.coherent_dma_mask; device->dev.release = vchiq_device_release; of_dma_configure(&device->dev, parent->of_node, true); ret = device_register(&device->dev); if (ret) { dev_err(parent, "Cannot register %s: %d\n", name, ret); put_device(&device->dev); return NULL; } return device; } void vchiq_device_unregister(struct vchiq_device *vchiq_dev) { device_unregister(&vchiq_dev->dev); } int vchiq_driver_register(struct vchiq_driver *vchiq_drv) { vchiq_drv->driver.bus = &vchiq_bus_type; return driver_register(&vchiq_drv->driver); } EXPORT_SYMBOL_GPL(vchiq_driver_register); void vchiq_driver_unregister(struct vchiq_driver *vchiq_drv) { driver_unregister(&vchiq_drv->driver); } EXPORT_SYMBOL_GPL(vchiq_driver_unregister);