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 ...@@ -237,6 +237,7 @@ config GENERIC_CPU_AUTOPROBE
config SOC_BUS config SOC_BUS
bool bool
select GLOB
source "drivers/base/regmap/Kconfig" source "drivers/base/regmap/Kconfig"
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/sys_soc.h> #include <linux/sys_soc.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/glob.h>
static DEFINE_IDA(soc_ida); static DEFINE_IDA(soc_ida);
...@@ -113,6 +114,12 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr ...@@ -113,6 +114,12 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
struct soc_device *soc_dev; struct soc_device *soc_dev;
int ret; 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); soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL);
if (!soc_dev) { if (!soc_dev) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -156,6 +163,78 @@ void soc_device_unregister(struct soc_device *soc_dev) ...@@ -156,6 +163,78 @@ void soc_device_unregister(struct soc_device *soc_dev)
static int __init soc_bus_register(void) static int __init soc_bus_register(void)
{ {
if (soc_bus_type.p)
return 0;
return bus_register(&soc_bus_type); return bus_register(&soc_bus_type);
} }
core_initcall(soc_bus_register); 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 { ...@@ -13,6 +13,7 @@ struct soc_device_attribute {
const char *family; const char *family;
const char *revision; const char *revision;
const char *soc_id; const char *soc_id;
const void *data;
}; };
/** /**
...@@ -34,4 +35,12 @@ void soc_device_unregister(struct soc_device *soc_dev); ...@@ -34,4 +35,12 @@ void soc_device_unregister(struct soc_device *soc_dev);
*/ */
struct device *soc_device_to_device(struct soc_device *soc); 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 */ #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