Loading drivers/base/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -237,6 +237,7 @@ config GENERIC_CPU_AUTOPROBE config SOC_BUS bool select GLOB source "drivers/base/regmap/Kconfig" Loading drivers/base/soc.c +79 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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); include/linux/sys_soc.h +9 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ struct soc_device_attribute { const char *family; const char *revision; const char *soc_id; const void *data; }; /** Loading @@ -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 */ Loading
drivers/base/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -237,6 +237,7 @@ config GENERIC_CPU_AUTOPROBE config SOC_BUS bool select GLOB source "drivers/base/regmap/Kconfig" Loading
drivers/base/soc.c +79 −0 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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);
include/linux/sys_soc.h +9 −0 Original line number Diff line number Diff line Loading @@ -13,6 +13,7 @@ struct soc_device_attribute { const char *family; const char *revision; const char *soc_id; const void *data; }; /** Loading @@ -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 */