Files
linux/drivers/platform/raspberrypi/vchiq-interface/vchiq_bus.c
Jai Luthra aa125180c6 platform/raspberrypi: Destage VCHIQ interface
Destage the VCHIQ interface driver to drivers/platform/raspberrypi.

There is still the remaining TODO item of improving the documentation,
which can be handled post destaging.

Secondly, multimedia drivers like codec and ISP that rely on this
interface need to be upstreamed. And lastly, the drivers that facilitate
the shared memory between VideoCore and Linux, like the vc-sm-cma driver
and vc_mem char driver also need to be upstreamed.

Signed-off-by: Jai Luthra <jai.luthra@ideasonboard.com>
Link: https://patch.msgid.link/20251029-vchiq-destage-v3-6-da8d6c83c2c5@ideasonboard.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2025-11-09 11:24:20 +09:00

113 lines
2.6 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* vchiq_device.c - VCHIQ generic device and bus-type
*
* Copyright (c) 2023 Ideas On Board Oy
*/
#include <linux/device/bus.h>
#include <linux/dma-mapping.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/raspberrypi/vchiq_arm.h>
#include <linux/raspberrypi/vchiq_bus.h>
static int vchiq_bus_type_match(struct device *dev, const 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);
}
static void vchiq_bus_remove(struct device *dev)
{
struct vchiq_device *device = to_vchiq_device(dev);
struct vchiq_driver *driver = to_vchiq_driver(dev->driver);
if (driver->remove)
driver->remove(device);
}
const struct bus_type vchiq_bus_type = {
.name = "vchiq-bus",
.match = vchiq_bus_type_match,
.uevent = vchiq_bus_uevent,
.probe = vchiq_bus_probe,
.remove = vchiq_bus_remove,
};
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;
device->drv_mgmt = dev_get_drvdata(parent);
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);