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

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
......@@ -237,6 +237,7 @@ config GENERIC_CPU_AUTOPROBE
config SOC_BUS
bool
select GLOB
source "drivers/base/regmap/Kconfig"
......
......@@ -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);
......@@ -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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment