Merge tag 'spi-fix-v6.8-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/spi
[linux-2.6-block.git] / drivers / of / module.c
CommitLineData
bd7a7ed7
MR
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Linux kernel module helpers.
4 */
5
6#include <linux/of.h>
e6506f06 7#include <linux/module.h>
bd7a7ed7
MR
8#include <linux/slab.h>
9#include <linux/string.h>
10
11ssize_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}
e6506f06
MR
46
47int 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}
74EXPORT_SYMBOL_GPL(of_request_module);