Merge tag 'soc-drivers-6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc
[linux-2.6-microblaze.git] / drivers / of / module.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Linux kernel module helpers.
4  */
5
6 #include <linux/of.h>
7 #include <linux/module.h>
8 #include <linux/slab.h>
9 #include <linux/string.h>
10
11 ssize_t of_modalias(const struct device_node *np, char *str, ssize_t len)
12 {
13         const char *compat;
14         char *c;
15         struct property *p;
16         ssize_t csize;
17         ssize_t tsize;
18
19         /* Name & Type */
20         /* %p eats all alphanum characters, so %c must be used here */
21         csize = snprintf(str, len, "of:N%pOFn%c%s", np, 'T',
22                          of_node_get_device_type(np));
23         tsize = csize;
24         len -= csize;
25         if (str)
26                 str += csize;
27
28         of_property_for_each_string(np, "compatible", p, compat) {
29                 csize = strlen(compat) + 1;
30                 tsize += csize;
31                 if (csize > len)
32                         continue;
33
34                 csize = snprintf(str, len, "C%s", compat);
35                 for (c = str; c; ) {
36                         c = strchr(c, ' ');
37                         if (c)
38                                 *c++ = '_';
39                 }
40                 len -= csize;
41                 str += csize;
42         }
43
44         return tsize;
45 }
46
47 int of_request_module(const struct device_node *np)
48 {
49         char *str;
50         ssize_t size;
51         int ret;
52
53         if (!np)
54                 return -ENODEV;
55
56         size = of_modalias(np, NULL, 0);
57         if (size < 0)
58                 return size;
59
60         /* Reserve an additional byte for the trailing '\0' */
61         size++;
62
63         str = kmalloc(size, GFP_KERNEL);
64         if (!str)
65                 return -ENOMEM;
66
67         of_modalias(np, str, size);
68         str[size - 1] = '\0';
69         ret = request_module(str);
70         kfree(str);
71
72         return ret;
73 }
74 EXPORT_SYMBOL_GPL(of_request_module);