162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2019-2020 Intel Corporation
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Please see Documentation/driver-api/auxiliary_bus.rst for more information.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#define pr_fmt(fmt) "%s:%s: " fmt, KBUILD_MODNAME, __func__
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/device.h>
1162306a36Sopenharmony_ci#include <linux/init.h>
1262306a36Sopenharmony_ci#include <linux/slab.h>
1362306a36Sopenharmony_ci#include <linux/module.h>
1462306a36Sopenharmony_ci#include <linux/pm_domain.h>
1562306a36Sopenharmony_ci#include <linux/pm_runtime.h>
1662306a36Sopenharmony_ci#include <linux/string.h>
1762306a36Sopenharmony_ci#include <linux/auxiliary_bus.h>
1862306a36Sopenharmony_ci#include "base.h"
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/**
2162306a36Sopenharmony_ci * DOC: PURPOSE
2262306a36Sopenharmony_ci *
2362306a36Sopenharmony_ci * In some subsystems, the functionality of the core device (PCI/ACPI/other) is
2462306a36Sopenharmony_ci * too complex for a single device to be managed by a monolithic driver (e.g.
2562306a36Sopenharmony_ci * Sound Open Firmware), multiple devices might implement a common intersection
2662306a36Sopenharmony_ci * of functionality (e.g. NICs + RDMA), or a driver may want to export an
2762306a36Sopenharmony_ci * interface for another subsystem to drive (e.g. SIOV Physical Function export
2862306a36Sopenharmony_ci * Virtual Function management).  A split of the functionality into child-
2962306a36Sopenharmony_ci * devices representing sub-domains of functionality makes it possible to
3062306a36Sopenharmony_ci * compartmentalize, layer, and distribute domain-specific concerns via a Linux
3162306a36Sopenharmony_ci * device-driver model.
3262306a36Sopenharmony_ci *
3362306a36Sopenharmony_ci * An example for this kind of requirement is the audio subsystem where a
3462306a36Sopenharmony_ci * single IP is handling multiple entities such as HDMI, Soundwire, local
3562306a36Sopenharmony_ci * devices such as mics/speakers etc. The split for the core's functionality
3662306a36Sopenharmony_ci * can be arbitrary or be defined by the DSP firmware topology and include
3762306a36Sopenharmony_ci * hooks for test/debug. This allows for the audio core device to be minimal
3862306a36Sopenharmony_ci * and focused on hardware-specific control and communication.
3962306a36Sopenharmony_ci *
4062306a36Sopenharmony_ci * Each auxiliary_device represents a part of its parent functionality. The
4162306a36Sopenharmony_ci * generic behavior can be extended and specialized as needed by encapsulating
4262306a36Sopenharmony_ci * an auxiliary_device within other domain-specific structures and the use of
4362306a36Sopenharmony_ci * .ops callbacks. Devices on the auxiliary bus do not share any structures and
4462306a36Sopenharmony_ci * the use of a communication channel with the parent is domain-specific.
4562306a36Sopenharmony_ci *
4662306a36Sopenharmony_ci * Note that ops are intended as a way to augment instance behavior within a
4762306a36Sopenharmony_ci * class of auxiliary devices, it is not the mechanism for exporting common
4862306a36Sopenharmony_ci * infrastructure from the parent. Consider EXPORT_SYMBOL_NS() to convey
4962306a36Sopenharmony_ci * infrastructure from the parent module to the auxiliary module(s).
5062306a36Sopenharmony_ci */
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/**
5362306a36Sopenharmony_ci * DOC: USAGE
5462306a36Sopenharmony_ci *
5562306a36Sopenharmony_ci * The auxiliary bus is to be used when a driver and one or more kernel
5662306a36Sopenharmony_ci * modules, who share a common header file with the driver, need a mechanism to
5762306a36Sopenharmony_ci * connect and provide access to a shared object allocated by the
5862306a36Sopenharmony_ci * auxiliary_device's registering driver.  The registering driver for the
5962306a36Sopenharmony_ci * auxiliary_device(s) and the kernel module(s) registering auxiliary_drivers
6062306a36Sopenharmony_ci * can be from the same subsystem, or from multiple subsystems.
6162306a36Sopenharmony_ci *
6262306a36Sopenharmony_ci * The emphasis here is on a common generic interface that keeps subsystem
6362306a36Sopenharmony_ci * customization out of the bus infrastructure.
6462306a36Sopenharmony_ci *
6562306a36Sopenharmony_ci * One example is a PCI network device that is RDMA-capable and exports a child
6662306a36Sopenharmony_ci * device to be driven by an auxiliary_driver in the RDMA subsystem.  The PCI
6762306a36Sopenharmony_ci * driver allocates and registers an auxiliary_device for each physical
6862306a36Sopenharmony_ci * function on the NIC.  The RDMA driver registers an auxiliary_driver that
6962306a36Sopenharmony_ci * claims each of these auxiliary_devices.  This conveys data/ops published by
7062306a36Sopenharmony_ci * the parent PCI device/driver to the RDMA auxiliary_driver.
7162306a36Sopenharmony_ci *
7262306a36Sopenharmony_ci * Another use case is for the PCI device to be split out into multiple sub
7362306a36Sopenharmony_ci * functions.  For each sub function an auxiliary_device is created.  A PCI sub
7462306a36Sopenharmony_ci * function driver binds to such devices that creates its own one or more class
7562306a36Sopenharmony_ci * devices.  A PCI sub function auxiliary device is likely to be contained in a
7662306a36Sopenharmony_ci * struct with additional attributes such as user defined sub function number
7762306a36Sopenharmony_ci * and optional attributes such as resources and a link to the parent device.
7862306a36Sopenharmony_ci * These attributes could be used by systemd/udev; and hence should be
7962306a36Sopenharmony_ci * initialized before a driver binds to an auxiliary_device.
8062306a36Sopenharmony_ci *
8162306a36Sopenharmony_ci * A key requirement for utilizing the auxiliary bus is that there is no
8262306a36Sopenharmony_ci * dependency on a physical bus, device, register accesses or regmap support.
8362306a36Sopenharmony_ci * These individual devices split from the core cannot live on the platform bus
8462306a36Sopenharmony_ci * as they are not physical devices that are controlled by DT/ACPI.  The same
8562306a36Sopenharmony_ci * argument applies for not using MFD in this scenario as MFD relies on
8662306a36Sopenharmony_ci * individual function devices being physical devices.
8762306a36Sopenharmony_ci */
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci/**
9062306a36Sopenharmony_ci * DOC: EXAMPLE
9162306a36Sopenharmony_ci *
9262306a36Sopenharmony_ci * Auxiliary devices are created and registered by a subsystem-level core
9362306a36Sopenharmony_ci * device that needs to break up its functionality into smaller fragments. One
9462306a36Sopenharmony_ci * way to extend the scope of an auxiliary_device is to encapsulate it within a
9562306a36Sopenharmony_ci * domain- pecific structure defined by the parent device. This structure
9662306a36Sopenharmony_ci * contains the auxiliary_device and any associated shared data/callbacks
9762306a36Sopenharmony_ci * needed to establish the connection with the parent.
9862306a36Sopenharmony_ci *
9962306a36Sopenharmony_ci * An example is:
10062306a36Sopenharmony_ci *
10162306a36Sopenharmony_ci * .. code-block:: c
10262306a36Sopenharmony_ci *
10362306a36Sopenharmony_ci *         struct foo {
10462306a36Sopenharmony_ci *		struct auxiliary_device auxdev;
10562306a36Sopenharmony_ci *		void (*connect)(struct auxiliary_device *auxdev);
10662306a36Sopenharmony_ci *		void (*disconnect)(struct auxiliary_device *auxdev);
10762306a36Sopenharmony_ci *		void *data;
10862306a36Sopenharmony_ci *        };
10962306a36Sopenharmony_ci *
11062306a36Sopenharmony_ci * The parent device then registers the auxiliary_device by calling
11162306a36Sopenharmony_ci * auxiliary_device_init(), and then auxiliary_device_add(), with the pointer
11262306a36Sopenharmony_ci * to the auxdev member of the above structure. The parent provides a name for
11362306a36Sopenharmony_ci * the auxiliary_device that, combined with the parent's KBUILD_MODNAME,
11462306a36Sopenharmony_ci * creates a match_name that is be used for matching and binding with a driver.
11562306a36Sopenharmony_ci *
11662306a36Sopenharmony_ci * Whenever an auxiliary_driver is registered, based on the match_name, the
11762306a36Sopenharmony_ci * auxiliary_driver's probe() is invoked for the matching devices.  The
11862306a36Sopenharmony_ci * auxiliary_driver can also be encapsulated inside custom drivers that make
11962306a36Sopenharmony_ci * the core device's functionality extensible by adding additional
12062306a36Sopenharmony_ci * domain-specific ops as follows:
12162306a36Sopenharmony_ci *
12262306a36Sopenharmony_ci * .. code-block:: c
12362306a36Sopenharmony_ci *
12462306a36Sopenharmony_ci *	struct my_ops {
12562306a36Sopenharmony_ci *		void (*send)(struct auxiliary_device *auxdev);
12662306a36Sopenharmony_ci *		void (*receive)(struct auxiliary_device *auxdev);
12762306a36Sopenharmony_ci *	};
12862306a36Sopenharmony_ci *
12962306a36Sopenharmony_ci *
13062306a36Sopenharmony_ci *	struct my_driver {
13162306a36Sopenharmony_ci *		struct auxiliary_driver auxiliary_drv;
13262306a36Sopenharmony_ci *		const struct my_ops ops;
13362306a36Sopenharmony_ci *	};
13462306a36Sopenharmony_ci *
13562306a36Sopenharmony_ci * An example of this type of usage is:
13662306a36Sopenharmony_ci *
13762306a36Sopenharmony_ci * .. code-block:: c
13862306a36Sopenharmony_ci *
13962306a36Sopenharmony_ci *	const struct auxiliary_device_id my_auxiliary_id_table[] = {
14062306a36Sopenharmony_ci *		{ .name = "foo_mod.foo_dev" },
14162306a36Sopenharmony_ci *		{ },
14262306a36Sopenharmony_ci *	};
14362306a36Sopenharmony_ci *
14462306a36Sopenharmony_ci *	const struct my_ops my_custom_ops = {
14562306a36Sopenharmony_ci *		.send = my_tx,
14662306a36Sopenharmony_ci *		.receive = my_rx,
14762306a36Sopenharmony_ci *	};
14862306a36Sopenharmony_ci *
14962306a36Sopenharmony_ci *	const struct my_driver my_drv = {
15062306a36Sopenharmony_ci *		.auxiliary_drv = {
15162306a36Sopenharmony_ci *			.name = "myauxiliarydrv",
15262306a36Sopenharmony_ci *			.id_table = my_auxiliary_id_table,
15362306a36Sopenharmony_ci *			.probe = my_probe,
15462306a36Sopenharmony_ci *			.remove = my_remove,
15562306a36Sopenharmony_ci *			.shutdown = my_shutdown,
15662306a36Sopenharmony_ci *		},
15762306a36Sopenharmony_ci *		.ops = my_custom_ops,
15862306a36Sopenharmony_ci *	};
15962306a36Sopenharmony_ci */
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_cistatic const struct auxiliary_device_id *auxiliary_match_id(const struct auxiliary_device_id *id,
16262306a36Sopenharmony_ci							    const struct auxiliary_device *auxdev)
16362306a36Sopenharmony_ci{
16462306a36Sopenharmony_ci	for (; id->name[0]; id++) {
16562306a36Sopenharmony_ci		const char *p = strrchr(dev_name(&auxdev->dev), '.');
16662306a36Sopenharmony_ci		int match_size;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci		if (!p)
16962306a36Sopenharmony_ci			continue;
17062306a36Sopenharmony_ci		match_size = p - dev_name(&auxdev->dev);
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ci		/* use dev_name(&auxdev->dev) prefix before last '.' char to match to */
17362306a36Sopenharmony_ci		if (strlen(id->name) == match_size &&
17462306a36Sopenharmony_ci		    !strncmp(dev_name(&auxdev->dev), id->name, match_size))
17562306a36Sopenharmony_ci			return id;
17662306a36Sopenharmony_ci	}
17762306a36Sopenharmony_ci	return NULL;
17862306a36Sopenharmony_ci}
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cistatic int auxiliary_match(struct device *dev, struct device_driver *drv)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci	struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
18362306a36Sopenharmony_ci	struct auxiliary_driver *auxdrv = to_auxiliary_drv(drv);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	return !!auxiliary_match_id(auxdrv->id_table, auxdev);
18662306a36Sopenharmony_ci}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_cistatic int auxiliary_uevent(const struct device *dev, struct kobj_uevent_env *env)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	const char *name, *p;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	name = dev_name(dev);
19362306a36Sopenharmony_ci	p = strrchr(name, '.');
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci	return add_uevent_var(env, "MODALIAS=%s%.*s", AUXILIARY_MODULE_PREFIX,
19662306a36Sopenharmony_ci			      (int)(p - name), name);
19762306a36Sopenharmony_ci}
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_cistatic const struct dev_pm_ops auxiliary_dev_pm_ops = {
20062306a36Sopenharmony_ci	SET_RUNTIME_PM_OPS(pm_generic_runtime_suspend, pm_generic_runtime_resume, NULL)
20162306a36Sopenharmony_ci	SET_SYSTEM_SLEEP_PM_OPS(pm_generic_suspend, pm_generic_resume)
20262306a36Sopenharmony_ci};
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_cistatic int auxiliary_bus_probe(struct device *dev)
20562306a36Sopenharmony_ci{
20662306a36Sopenharmony_ci	struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver);
20762306a36Sopenharmony_ci	struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
20862306a36Sopenharmony_ci	int ret;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	ret = dev_pm_domain_attach(dev, true);
21162306a36Sopenharmony_ci	if (ret) {
21262306a36Sopenharmony_ci		dev_warn(dev, "Failed to attach to PM Domain : %d\n", ret);
21362306a36Sopenharmony_ci		return ret;
21462306a36Sopenharmony_ci	}
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	ret = auxdrv->probe(auxdev, auxiliary_match_id(auxdrv->id_table, auxdev));
21762306a36Sopenharmony_ci	if (ret)
21862306a36Sopenharmony_ci		dev_pm_domain_detach(dev, true);
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	return ret;
22162306a36Sopenharmony_ci}
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_cistatic void auxiliary_bus_remove(struct device *dev)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	struct auxiliary_driver *auxdrv = to_auxiliary_drv(dev->driver);
22662306a36Sopenharmony_ci	struct auxiliary_device *auxdev = to_auxiliary_dev(dev);
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	if (auxdrv->remove)
22962306a36Sopenharmony_ci		auxdrv->remove(auxdev);
23062306a36Sopenharmony_ci	dev_pm_domain_detach(dev, true);
23162306a36Sopenharmony_ci}
23262306a36Sopenharmony_ci
23362306a36Sopenharmony_cistatic void auxiliary_bus_shutdown(struct device *dev)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	struct auxiliary_driver *auxdrv = NULL;
23662306a36Sopenharmony_ci	struct auxiliary_device *auxdev;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci	if (dev->driver) {
23962306a36Sopenharmony_ci		auxdrv = to_auxiliary_drv(dev->driver);
24062306a36Sopenharmony_ci		auxdev = to_auxiliary_dev(dev);
24162306a36Sopenharmony_ci	}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	if (auxdrv && auxdrv->shutdown)
24462306a36Sopenharmony_ci		auxdrv->shutdown(auxdev);
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_cistatic struct bus_type auxiliary_bus_type = {
24862306a36Sopenharmony_ci	.name = "auxiliary",
24962306a36Sopenharmony_ci	.probe = auxiliary_bus_probe,
25062306a36Sopenharmony_ci	.remove = auxiliary_bus_remove,
25162306a36Sopenharmony_ci	.shutdown = auxiliary_bus_shutdown,
25262306a36Sopenharmony_ci	.match = auxiliary_match,
25362306a36Sopenharmony_ci	.uevent = auxiliary_uevent,
25462306a36Sopenharmony_ci	.pm = &auxiliary_dev_pm_ops,
25562306a36Sopenharmony_ci};
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci/**
25862306a36Sopenharmony_ci * auxiliary_device_init - check auxiliary_device and initialize
25962306a36Sopenharmony_ci * @auxdev: auxiliary device struct
26062306a36Sopenharmony_ci *
26162306a36Sopenharmony_ci * This is the second step in the three-step process to register an
26262306a36Sopenharmony_ci * auxiliary_device.
26362306a36Sopenharmony_ci *
26462306a36Sopenharmony_ci * When this function returns an error code, then the device_initialize will
26562306a36Sopenharmony_ci * *not* have been performed, and the caller will be responsible to free any
26662306a36Sopenharmony_ci * memory allocated for the auxiliary_device in the error path directly.
26762306a36Sopenharmony_ci *
26862306a36Sopenharmony_ci * It returns 0 on success.  On success, the device_initialize has been
26962306a36Sopenharmony_ci * performed.  After this point any error unwinding will need to include a call
27062306a36Sopenharmony_ci * to auxiliary_device_uninit().  In this post-initialize error scenario, a call
27162306a36Sopenharmony_ci * to the device's .release callback will be triggered, and all memory clean-up
27262306a36Sopenharmony_ci * is expected to be handled there.
27362306a36Sopenharmony_ci */
27462306a36Sopenharmony_ciint auxiliary_device_init(struct auxiliary_device *auxdev)
27562306a36Sopenharmony_ci{
27662306a36Sopenharmony_ci	struct device *dev = &auxdev->dev;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	if (!dev->parent) {
27962306a36Sopenharmony_ci		pr_err("auxiliary_device has a NULL dev->parent\n");
28062306a36Sopenharmony_ci		return -EINVAL;
28162306a36Sopenharmony_ci	}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	if (!auxdev->name) {
28462306a36Sopenharmony_ci		pr_err("auxiliary_device has a NULL name\n");
28562306a36Sopenharmony_ci		return -EINVAL;
28662306a36Sopenharmony_ci	}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	dev->bus = &auxiliary_bus_type;
28962306a36Sopenharmony_ci	device_initialize(&auxdev->dev);
29062306a36Sopenharmony_ci	return 0;
29162306a36Sopenharmony_ci}
29262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(auxiliary_device_init);
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci/**
29562306a36Sopenharmony_ci * __auxiliary_device_add - add an auxiliary bus device
29662306a36Sopenharmony_ci * @auxdev: auxiliary bus device to add to the bus
29762306a36Sopenharmony_ci * @modname: name of the parent device's driver module
29862306a36Sopenharmony_ci *
29962306a36Sopenharmony_ci * This is the third step in the three-step process to register an
30062306a36Sopenharmony_ci * auxiliary_device.
30162306a36Sopenharmony_ci *
30262306a36Sopenharmony_ci * This function must be called after a successful call to
30362306a36Sopenharmony_ci * auxiliary_device_init(), which will perform the device_initialize.  This
30462306a36Sopenharmony_ci * means that if this returns an error code, then a call to
30562306a36Sopenharmony_ci * auxiliary_device_uninit() must be performed so that the .release callback
30662306a36Sopenharmony_ci * will be triggered to free the memory associated with the auxiliary_device.
30762306a36Sopenharmony_ci *
30862306a36Sopenharmony_ci * The expectation is that users will call the "auxiliary_device_add" macro so
30962306a36Sopenharmony_ci * that the caller's KBUILD_MODNAME is automatically inserted for the modname
31062306a36Sopenharmony_ci * parameter.  Only if a user requires a custom name would this version be
31162306a36Sopenharmony_ci * called directly.
31262306a36Sopenharmony_ci */
31362306a36Sopenharmony_ciint __auxiliary_device_add(struct auxiliary_device *auxdev, const char *modname)
31462306a36Sopenharmony_ci{
31562306a36Sopenharmony_ci	struct device *dev = &auxdev->dev;
31662306a36Sopenharmony_ci	int ret;
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	if (!modname) {
31962306a36Sopenharmony_ci		dev_err(dev, "auxiliary device modname is NULL\n");
32062306a36Sopenharmony_ci		return -EINVAL;
32162306a36Sopenharmony_ci	}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	ret = dev_set_name(dev, "%s.%s.%d", modname, auxdev->name, auxdev->id);
32462306a36Sopenharmony_ci	if (ret) {
32562306a36Sopenharmony_ci		dev_err(dev, "auxiliary device dev_set_name failed: %d\n", ret);
32662306a36Sopenharmony_ci		return ret;
32762306a36Sopenharmony_ci	}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	ret = device_add(dev);
33062306a36Sopenharmony_ci	if (ret)
33162306a36Sopenharmony_ci		dev_err(dev, "adding auxiliary device failed!: %d\n", ret);
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	return ret;
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__auxiliary_device_add);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci/**
33862306a36Sopenharmony_ci * auxiliary_find_device - auxiliary device iterator for locating a particular device.
33962306a36Sopenharmony_ci * @start: Device to begin with
34062306a36Sopenharmony_ci * @data: Data to pass to match function
34162306a36Sopenharmony_ci * @match: Callback function to check device
34262306a36Sopenharmony_ci *
34362306a36Sopenharmony_ci * This function returns a reference to a device that is 'found'
34462306a36Sopenharmony_ci * for later use, as determined by the @match callback.
34562306a36Sopenharmony_ci *
34662306a36Sopenharmony_ci * The reference returned should be released with put_device().
34762306a36Sopenharmony_ci *
34862306a36Sopenharmony_ci * The callback should return 0 if the device doesn't match and non-zero
34962306a36Sopenharmony_ci * if it does.  If the callback returns non-zero, this function will
35062306a36Sopenharmony_ci * return to the caller and not iterate over any more devices.
35162306a36Sopenharmony_ci */
35262306a36Sopenharmony_cistruct auxiliary_device *auxiliary_find_device(struct device *start,
35362306a36Sopenharmony_ci					       const void *data,
35462306a36Sopenharmony_ci					       int (*match)(struct device *dev, const void *data))
35562306a36Sopenharmony_ci{
35662306a36Sopenharmony_ci	struct device *dev;
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	dev = bus_find_device(&auxiliary_bus_type, start, data, match);
35962306a36Sopenharmony_ci	if (!dev)
36062306a36Sopenharmony_ci		return NULL;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	return to_auxiliary_dev(dev);
36362306a36Sopenharmony_ci}
36462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(auxiliary_find_device);
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci/**
36762306a36Sopenharmony_ci * __auxiliary_driver_register - register a driver for auxiliary bus devices
36862306a36Sopenharmony_ci * @auxdrv: auxiliary_driver structure
36962306a36Sopenharmony_ci * @owner: owning module/driver
37062306a36Sopenharmony_ci * @modname: KBUILD_MODNAME for parent driver
37162306a36Sopenharmony_ci *
37262306a36Sopenharmony_ci * The expectation is that users will call the "auxiliary_driver_register"
37362306a36Sopenharmony_ci * macro so that the caller's KBUILD_MODNAME is automatically inserted for the
37462306a36Sopenharmony_ci * modname parameter.  Only if a user requires a custom name would this version
37562306a36Sopenharmony_ci * be called directly.
37662306a36Sopenharmony_ci */
37762306a36Sopenharmony_ciint __auxiliary_driver_register(struct auxiliary_driver *auxdrv,
37862306a36Sopenharmony_ci				struct module *owner, const char *modname)
37962306a36Sopenharmony_ci{
38062306a36Sopenharmony_ci	int ret;
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	if (WARN_ON(!auxdrv->probe) || WARN_ON(!auxdrv->id_table))
38362306a36Sopenharmony_ci		return -EINVAL;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	if (auxdrv->name)
38662306a36Sopenharmony_ci		auxdrv->driver.name = kasprintf(GFP_KERNEL, "%s.%s", modname,
38762306a36Sopenharmony_ci						auxdrv->name);
38862306a36Sopenharmony_ci	else
38962306a36Sopenharmony_ci		auxdrv->driver.name = kasprintf(GFP_KERNEL, "%s", modname);
39062306a36Sopenharmony_ci	if (!auxdrv->driver.name)
39162306a36Sopenharmony_ci		return -ENOMEM;
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	auxdrv->driver.owner = owner;
39462306a36Sopenharmony_ci	auxdrv->driver.bus = &auxiliary_bus_type;
39562306a36Sopenharmony_ci	auxdrv->driver.mod_name = modname;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	ret = driver_register(&auxdrv->driver);
39862306a36Sopenharmony_ci	if (ret)
39962306a36Sopenharmony_ci		kfree(auxdrv->driver.name);
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	return ret;
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__auxiliary_driver_register);
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci/**
40662306a36Sopenharmony_ci * auxiliary_driver_unregister - unregister a driver
40762306a36Sopenharmony_ci * @auxdrv: auxiliary_driver structure
40862306a36Sopenharmony_ci */
40962306a36Sopenharmony_civoid auxiliary_driver_unregister(struct auxiliary_driver *auxdrv)
41062306a36Sopenharmony_ci{
41162306a36Sopenharmony_ci	driver_unregister(&auxdrv->driver);
41262306a36Sopenharmony_ci	kfree(auxdrv->driver.name);
41362306a36Sopenharmony_ci}
41462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(auxiliary_driver_unregister);
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_civoid __init auxiliary_bus_init(void)
41762306a36Sopenharmony_ci{
41862306a36Sopenharmony_ci	WARN_ON(bus_register(&auxiliary_bus_type));
41962306a36Sopenharmony_ci}
420