Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6ecdf76b authored by Ulf Hansson's avatar Ulf Hansson
Browse files

Merge tag 'soc-device-match-tag1' into next

Merge the immutable soc-device-match-tag1 provided by Geert Uytterhoeven
to pull in the new soc_device_match() interface for matching against
soc_bus attributes.
parents fb3470f7 da65a158
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -237,6 +237,7 @@ config GENERIC_CPU_AUTOPROBE

config SOC_BUS
	bool
	select GLOB

source "drivers/base/regmap/Kconfig"

+79 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
#include <linux/spinlock.h>
#include <linux/sys_soc.h>
#include <linux/err.h>
#include <linux/glob.h>

static DEFINE_IDA(soc_ida);

@@ -113,6 +114,12 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
	struct soc_device *soc_dev;
	int ret;

	if (!soc_bus_type.p) {
		ret = bus_register(&soc_bus_type);
		if (ret)
			goto out1;
	}

	soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL);
	if (!soc_dev) {
		ret = -ENOMEM;
@@ -156,6 +163,78 @@ void soc_device_unregister(struct soc_device *soc_dev)

static int __init soc_bus_register(void)
{
	if (soc_bus_type.p)
		return 0;

	return bus_register(&soc_bus_type);
}
core_initcall(soc_bus_register);

static int soc_device_match_one(struct device *dev, void *arg)
{
	struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
	const struct soc_device_attribute *match = arg;

	if (match->machine &&
	    (!soc_dev->attr->machine ||
	     !glob_match(match->machine, soc_dev->attr->machine)))
		return 0;

	if (match->family &&
	    (!soc_dev->attr->family ||
	     !glob_match(match->family, soc_dev->attr->family)))
		return 0;

	if (match->revision &&
	    (!soc_dev->attr->revision ||
	     !glob_match(match->revision, soc_dev->attr->revision)))
		return 0;

	if (match->soc_id &&
	    (!soc_dev->attr->soc_id ||
	     !glob_match(match->soc_id, soc_dev->attr->soc_id)))
		return 0;

	return 1;
}

/*
 * soc_device_match - identify the SoC in the machine
 * @matches: zero-terminated array of possible matches
 *
 * returns the first matching entry of the argument array, or NULL
 * if none of them match.
 *
 * This function is meant as a helper in place of of_match_node()
 * in cases where either no device tree is available or the information
 * in a device node is insufficient to identify a particular variant
 * by its compatible strings or other properties. For new devices,
 * the DT binding should always provide unique compatible strings
 * that allow the use of of_match_node() instead.
 *
 * The calling function can use the .data entry of the
 * soc_device_attribute to pass a structure or function pointer for
 * each entry.
 */
const struct soc_device_attribute *soc_device_match(
	const struct soc_device_attribute *matches)
{
	int ret = 0;

	if (!matches)
		return NULL;

	while (!ret) {
		if (!(matches->machine || matches->family ||
		      matches->revision || matches->soc_id))
			break;
		ret = bus_for_each_dev(&soc_bus_type, NULL, (void *)matches,
				       soc_device_match_one);
		if (!ret)
			matches++;
		else
			return matches;
	}
	return NULL;
}
EXPORT_SYMBOL_GPL(soc_device_match);
+9 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@ struct soc_device_attribute {
	const char *family;
	const char *revision;
	const char *soc_id;
	const void *data;
};

/**
@@ -34,4 +35,12 @@ void soc_device_unregister(struct soc_device *soc_dev);
 */
struct device *soc_device_to_device(struct soc_device *soc);

#ifdef CONFIG_SOC_BUS
const struct soc_device_attribute *soc_device_match(
	const struct soc_device_attribute *matches);
#else
static inline const struct soc_device_attribute *soc_device_match(
	const struct soc_device_attribute *matches) { return NULL; }
#endif

#endif /* __SOC_BUS_H */