1
0
Fork 0

soc_device_match() interface for matching against soc_bus attributes

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJYJDsDAAoJEEgEtLw/Ve77SFEP/1E64/Toxi48RM2e37mtbRRp
 Dye1FUXxJY67USKx9eBYMGUHaV+QOxiifN7SfU0JgovGYtyAZeerbEbibT2TYN3V
 c9OP/sKUdAriqv/U4MX+2YiQJJS7zHvVt4yk+ZMU3e9dj8d2ndZKCw1rueGDZekn
 YjI0yNJdHsd08iZ+zrz/UaGeb0lZOzsQNIH+9rMs3GHfwXzLhh6NoYvQVrneu/Cd
 0mDKrFqPVmWNETr2qoyZtrVQefgOKffmw10MfFfeItCMWYpbdjBhR0EuONSMv45q
 Sk3IHNUU049FnU7ucJHJIIcsPqXUicRDbyonotb8QDx//TCwvPwkiEt2tW/TRgBn
 J9I+q9sIhLTcHGxuYTaWNvNUo9PGcKHWp+7dHhuPs9R1s8OqpFS/Fu371jQmFxGr
 6eSxMED7aGb3qJKKp60vFBnKcivVyRpj0mpwtLDrFLZwl+hT9dH4gto7SBuA6x9U
 8XnEyySYsoIETyLhuiladURs9UssbHfAxeoX5zMioZ13PoDnnQQSlhUNnpc7XAtc
 skTa23JsZAfV+UTvu6A//cGd+Jch72Gf6fIVCNGxkn9+FPA4RAktpGciHTSpKRzF
 +sAAo8g/usW3q0GQQWZqzJZxbOQ8B8dyMTXtp2LT4HGrZT67fJS2tRVMl9X8t+tk
 CnCCUJ/FcghiP6/Ou4zM
 =xyGw
 -----END PGP SIGNATURE-----

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.
hifive-unleashed-5.1
Ulf Hansson 2016-11-29 09:09:09 +01:00
commit 6ecdf76b8f
3 changed files with 89 additions and 0 deletions

View File

@ -237,6 +237,7 @@ config GENERIC_CPU_AUTOPROBE
config SOC_BUS
bool
select GLOB
source "drivers/base/regmap/Kconfig"

View File

@ -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);

View File

@ -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 */