Commit | Line | Data |
---|---|---|
af6074fc | 1 | // SPDX-License-Identifier: GPL-2.0 |
f85ff305 SR |
2 | #include <linux/kernel.h> |
3 | #include <linux/of.h> | |
f898f8db | 4 | #include <linux/of_device.h> |
1f5c69aa MK |
5 | #include <linux/of_address.h> |
6 | #include <linux/of_iommu.h> | |
ce5cb67c | 7 | #include <linux/of_reserved_mem.h> |
e0d07278 | 8 | #include <linux/dma-direct.h> /* for bus_dma_region */ |
0a0f0d8b | 9 | #include <linux/dma-map-ops.h> |
f85ff305 | 10 | #include <linux/init.h> |
f85ff305 SR |
11 | #include <linux/mod_devicetable.h> |
12 | #include <linux/slab.h> | |
72328883 | 13 | #include <linux/platform_device.h> |
f85ff305 SR |
14 | |
15 | #include <asm/errno.h> | |
ced4eec9 | 16 | #include "of_private.h" |
f85ff305 | 17 | |
f85ff305 | 18 | /** |
44504b2b | 19 | * of_match_device - Tell if a struct device matches an of_device_id list |
8e94fd36 | 20 | * @matches: array of of device match structures to search in |
f85ff305 SR |
21 | * @dev: the of device structure to match against |
22 | * | |
2dc11581 | 23 | * Used by a driver to check whether an platform_device present in the |
f85ff305 SR |
24 | * system is in its list of supported devices. |
25 | */ | |
26 | const struct of_device_id *of_match_device(const struct of_device_id *matches, | |
44504b2b | 27 | const struct device *dev) |
f85ff305 | 28 | { |
9b22c17a | 29 | if (!matches || !dev->of_node || dev->of_node_reused) |
f85ff305 | 30 | return NULL; |
44504b2b | 31 | return of_match_node(matches, dev->of_node); |
f85ff305 SR |
32 | } |
33 | EXPORT_SYMBOL(of_match_device); | |
34 | ||
f3cfd136 | 35 | static void |
ce5cb67c WD |
36 | of_dma_set_restricted_buffer(struct device *dev, struct device_node *np) |
37 | { | |
38 | struct device_node *node, *of_node = dev->of_node; | |
39 | int count, i; | |
40 | ||
f3cfd136 WD |
41 | if (!IS_ENABLED(CONFIG_DMA_RESTRICTED_POOL)) |
42 | return; | |
43 | ||
ce5cb67c WD |
44 | count = of_property_count_elems_of_size(of_node, "memory-region", |
45 | sizeof(u32)); | |
46 | /* | |
47 | * If dev->of_node doesn't exist or doesn't contain memory-region, try | |
48 | * the OF node having DMA configuration. | |
49 | */ | |
50 | if (count <= 0) { | |
51 | of_node = np; | |
52 | count = of_property_count_elems_of_size( | |
53 | of_node, "memory-region", sizeof(u32)); | |
54 | } | |
55 | ||
56 | for (i = 0; i < count; i++) { | |
57 | node = of_parse_phandle(of_node, "memory-region", i); | |
58 | /* | |
59 | * There might be multiple memory regions, but only one | |
60 | * restricted-dma-pool region is allowed. | |
61 | */ | |
62 | if (of_device_is_compatible(node, "restricted-dma-pool") && | |
d17e37c4 LH |
63 | of_device_is_available(node)) { |
64 | of_node_put(node); | |
f3cfd136 | 65 | break; |
d17e37c4 LH |
66 | } |
67 | of_node_put(node); | |
ce5cb67c WD |
68 | } |
69 | ||
31c8025f DB |
70 | /* |
71 | * Attempt to initialize a restricted-dma-pool region if one was found. | |
72 | * Note that count can hold a negative error code. | |
73 | */ | |
74 | if (i < count && of_reserved_mem_device_init_by_idx(dev, of_node, i)) | |
f3cfd136 | 75 | dev_warn(dev, "failed to initialise \"restricted-dma-pool\" memory node\n"); |
ce5cb67c WD |
76 | } |
77 | ||
1f5c69aa | 78 | /** |
cb61e9db | 79 | * of_dma_configure_id - Setup DMA configuration |
1f5c69aa MK |
80 | * @dev: Device to apply DMA configuration |
81 | * @np: Pointer to OF node having DMA configuration | |
3d6ce86e CH |
82 | * @force_dma: Whether device is to be set up by of_dma_configure() even if |
83 | * DMA capability is not explicitly described by firmware. | |
a081bd4a | 84 | * @id: Optional const pointer value input id |
1f5c69aa MK |
85 | * |
86 | * Try to get devices's DMA configuration from DT and update it | |
87 | * accordingly. | |
88 | * | |
89 | * If platform code needs to use its own special DMA configuration, it | |
90 | * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events | |
91 | * to fix up DMA configuration. | |
92 | */ | |
a081bd4a LP |
93 | int of_dma_configure_id(struct device *dev, struct device_node *np, |
94 | bool force_dma, const u32 *id) | |
1f5c69aa | 95 | { |
e0d07278 | 96 | const struct bus_dma_region *map = NULL; |
f1ad5338 | 97 | struct device_node *bus_np; |
48ab6d5d | 98 | u64 dma_start = 0; |
e0d07278 JQ |
99 | u64 mask, end, size = 0; |
100 | bool coherent; | |
6ff6e184 | 101 | int iommu_ret; |
e0d07278 | 102 | int ret; |
1f5c69aa | 103 | |
f1ad5338 RM |
104 | if (np == dev->of_node) |
105 | bus_np = __of_get_dma_parent(np); | |
106 | else | |
107 | bus_np = of_node_get(np); | |
108 | ||
109 | ret = of_dma_get_range(bus_np, &map); | |
110 | of_node_put(bus_np); | |
1f5c69aa | 111 | if (ret < 0) { |
72328883 RM |
112 | /* |
113 | * For legacy reasons, we have to assume some devices need | |
114 | * DMA configuration regardless of whether "dma-ranges" is | |
115 | * correctly specified or not. | |
116 | */ | |
3d6ce86e | 117 | if (!force_dma) |
72328883 | 118 | return ret == -ENODEV ? 0 : ret; |
1f5c69aa | 119 | } else { |
e0d07278 | 120 | const struct bus_dma_region *r = map; |
48ab6d5d | 121 | u64 dma_end = 0; |
e0d07278 JQ |
122 | |
123 | /* Determine the overall bounds of all DMA regions */ | |
495023e4 | 124 | for (dma_start = ~0; r->size; r++) { |
e0d07278 JQ |
125 | /* Take lower and upper limits */ |
126 | if (r->dma_start < dma_start) | |
127 | dma_start = r->dma_start; | |
128 | if (r->dma_start + r->size > dma_end) | |
129 | dma_end = r->dma_start + r->size; | |
130 | } | |
131 | size = dma_end - dma_start; | |
0c79c81c MK |
132 | |
133 | /* | |
134 | * Add a work around to treat the size as mask + 1 in case | |
135 | * it is defined in DT as a mask. | |
136 | */ | |
137 | if (size & 1) { | |
e0d07278 | 138 | dev_warn(dev, "Invalid size 0x%llx for dma-range(s)\n", |
0c79c81c MK |
139 | size); |
140 | size = size + 1; | |
141 | } | |
142 | ||
143 | if (!size) { | |
144 | dev_err(dev, "Adjusted size 0x%llx invalid\n", size); | |
e0d07278 | 145 | kfree(map); |
7b07cbef | 146 | return -EINVAL; |
0c79c81c | 147 | } |
1f5c69aa MK |
148 | } |
149 | ||
72328883 | 150 | /* |
4d8bde88 RM |
151 | * If @dev is expected to be DMA-capable then the bus code that created |
152 | * it should have initialised its dma_mask pointer by this point. For | |
153 | * now, we'll continue the legacy behaviour of coercing it to the | |
154 | * coherent mask if not, but we'll no longer do so quietly. | |
72328883 | 155 | */ |
4d8bde88 RM |
156 | if (!dev->dma_mask) { |
157 | dev_warn(dev, "DMA mask not set\n"); | |
72328883 | 158 | dev->dma_mask = &dev->coherent_dma_mask; |
4d8bde88 | 159 | } |
72328883 | 160 | |
4d8bde88 | 161 | if (!size && dev->coherent_dma_mask) |
72328883 | 162 | size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1); |
4d8bde88 RM |
163 | else if (!size) |
164 | size = 1ULL << 32; | |
72328883 | 165 | |
9a6d7298 MK |
166 | /* |
167 | * Limit coherent and dma mask based on size and default mask | |
168 | * set by the driver. | |
169 | */ | |
e0d07278 | 170 | end = dma_start + size - 1; |
a7ba70f1 | 171 | mask = DMA_BIT_MASK(ilog2(end) + 1); |
ee7b1f31 RM |
172 | dev->coherent_dma_mask &= mask; |
173 | *dev->dma_mask &= mask; | |
89c7cb16 YW |
174 | /* ...but only set bus limit and range map if we found valid dma-ranges earlier */ |
175 | if (!ret) { | |
a7ba70f1 | 176 | dev->bus_dma_limit = end; |
89c7cb16 YW |
177 | dev->dma_range_map = map; |
178 | } | |
9a6d7298 | 179 | |
1f5c69aa MK |
180 | coherent = of_dma_is_coherent(np); |
181 | dev_dbg(dev, "device is%sdma coherent\n", | |
182 | coherent ? " " : " not "); | |
183 | ||
6ff6e184 JG |
184 | iommu_ret = of_iommu_configure(dev, np, id); |
185 | if (iommu_ret == -EPROBE_DEFER) { | |
89c7cb16 YW |
186 | /* Don't touch range map if it wasn't set from a valid dma-ranges */ |
187 | if (!ret) | |
188 | dev->dma_range_map = NULL; | |
e0d07278 | 189 | kfree(map); |
a37b19a3 | 190 | return -EPROBE_DEFER; |
6ff6e184 JG |
191 | } else if (iommu_ret == -ENODEV) { |
192 | dev_dbg(dev, "device is not behind an iommu\n"); | |
193 | } else if (iommu_ret) { | |
194 | dev_err(dev, "iommu configuration for device failed with %pe\n", | |
195 | ERR_PTR(iommu_ret)); | |
7b07cbef | 196 | |
6ff6e184 JG |
197 | /* |
198 | * Historically this routine doesn't fail driver probing | |
199 | * due to errors in of_iommu_configure() | |
200 | */ | |
201 | } else | |
202 | dev_dbg(dev, "device is behind an iommu\n"); | |
1f5c69aa | 203 | |
4720287c | 204 | arch_setup_dma_ops(dev, dma_start, size, coherent); |
7b07cbef | 205 | |
6ff6e184 | 206 | if (iommu_ret) |
f3cfd136 | 207 | of_dma_set_restricted_buffer(dev, np); |
fec9b625 | 208 | |
7b07cbef | 209 | return 0; |
1f5c69aa | 210 | } |
a081bd4a | 211 | EXPORT_SYMBOL_GPL(of_dma_configure_id); |
1f5c69aa | 212 | |
3386e0fa JE |
213 | const void *of_device_get_match_data(const struct device *dev) |
214 | { | |
215 | const struct of_device_id *match; | |
216 | ||
217 | match = of_match_device(dev->driver->of_match_table, dev); | |
218 | if (!match) | |
219 | return NULL; | |
220 | ||
221 | return match->data; | |
222 | } | |
223 | EXPORT_SYMBOL(of_device_get_match_data); | |
224 | ||
0634c295 RH |
225 | /** |
226 | * of_device_modalias - Fill buffer with newline terminated modalias string | |
cb61e9db LJ |
227 | * @dev: Calling device |
228 | * @str: Modalias string | |
229 | * @len: Size of @str | |
0634c295 RH |
230 | */ |
231 | ssize_t of_device_modalias(struct device *dev, char *str, ssize_t len) | |
232 | { | |
5c3d15e1 MR |
233 | ssize_t sl; |
234 | ||
235 | if (!dev || !dev->of_node || dev->of_node_reused) | |
236 | return -ENODEV; | |
237 | ||
238 | sl = of_modalias(dev->of_node, str, len - 2); | |
0634c295 RH |
239 | if (sl < 0) |
240 | return sl; | |
08ab58d9 BA |
241 | if (sl > len - 2) |
242 | return -ENOMEM; | |
0634c295 RH |
243 | |
244 | str[sl++] = '\n'; | |
245 | str[sl] = 0; | |
246 | return sl; | |
247 | } | |
248 | EXPORT_SYMBOL_GPL(of_device_modalias); | |
249 | ||
dd27dcda GL |
250 | /** |
251 | * of_device_uevent - Display OF related uevent information | |
9f041c5d GKH |
252 | * @dev: Device to display the uevent information for |
253 | * @env: Kernel object's userspace event reference to fill up | |
dd27dcda | 254 | */ |
9f041c5d | 255 | void of_device_uevent(const struct device *dev, struct kobj_uevent_env *env) |
dd27dcda | 256 | { |
e8b1dee2 | 257 | const char *compat, *type; |
ced4eec9 | 258 | struct alias_prop *app; |
bc575064 RH |
259 | struct property *p; |
260 | int seen = 0; | |
dd27dcda GL |
261 | |
262 | if ((!dev) || (!dev->of_node)) | |
07d57a32 | 263 | return; |
dd27dcda | 264 | |
a613b26a | 265 | add_uevent_var(env, "OF_NAME=%pOFn", dev->of_node); |
0d638a07 | 266 | add_uevent_var(env, "OF_FULLNAME=%pOF", dev->of_node); |
e8b1dee2 RH |
267 | type = of_node_get_device_type(dev->of_node); |
268 | if (type) | |
269 | add_uevent_var(env, "OF_TYPE=%s", type); | |
dd27dcda GL |
270 | |
271 | /* Since the compatible field can contain pretty much anything | |
272 | * it's not really legal to split it out with commas. We split it | |
273 | * up using a number of environment variables instead. */ | |
bc575064 | 274 | of_property_for_each_string(dev->of_node, "compatible", p, compat) { |
07d57a32 | 275 | add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat); |
dd27dcda GL |
276 | seen++; |
277 | } | |
07d57a32 | 278 | add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen); |
ced4eec9 SM |
279 | |
280 | seen = 0; | |
c05aba2b | 281 | mutex_lock(&of_mutex); |
ced4eec9 SM |
282 | list_for_each_entry(app, &aliases_lookup, link) { |
283 | if (dev->of_node == app->np) { | |
284 | add_uevent_var(env, "OF_ALIAS_%d=%s", seen, | |
285 | app->alias); | |
286 | seen++; | |
287 | } | |
288 | } | |
c05aba2b | 289 | mutex_unlock(&of_mutex); |
07d57a32 | 290 | } |
97c23217 | 291 | EXPORT_SYMBOL_GPL(of_device_uevent); |
dd27dcda | 292 | |
a77ad4bf | 293 | int of_device_uevent_modalias(const struct device *dev, struct kobj_uevent_env *env) |
07d57a32 GL |
294 | { |
295 | int sl; | |
296 | ||
553bd297 | 297 | if ((!dev) || (!dev->of_node) || dev->of_node_reused) |
07d57a32 | 298 | return -ENODEV; |
dd27dcda | 299 | |
07d57a32 | 300 | /* Devicetree modalias is tricky, we add it in 2 steps */ |
dd27dcda GL |
301 | if (add_uevent_var(env, "MODALIAS=")) |
302 | return -ENOMEM; | |
303 | ||
5c3d15e1 MR |
304 | sl = of_modalias(dev->of_node, &env->buf[env->buflen-1], |
305 | sizeof(env->buf) - env->buflen); | |
2295bed9 AS |
306 | if (sl < 0) |
307 | return sl; | |
dd27dcda GL |
308 | if (sl >= (sizeof(env->buf) - env->buflen)) |
309 | return -ENOMEM; | |
310 | env->buflen += sl; | |
311 | ||
312 | return 0; | |
313 | } | |
7a3b7cd3 | 314 | EXPORT_SYMBOL_GPL(of_device_uevent_modalias); |
7f38b700 MR |
315 | |
316 | /** | |
317 | * of_device_make_bus_id - Use the device node data to assign a unique name | |
318 | * @dev: pointer to device structure that is linked to a device tree node | |
319 | * | |
320 | * This routine will first try using the translated bus address to | |
321 | * derive a unique name. If it cannot, then it will prepend names from | |
322 | * parent nodes until a unique name can be derived. | |
323 | */ | |
324 | void of_device_make_bus_id(struct device *dev) | |
325 | { | |
326 | struct device_node *node = dev->of_node; | |
327 | const __be32 *reg; | |
328 | u64 addr; | |
329 | u32 mask; | |
330 | ||
331 | /* Construct the name, using parent nodes if necessary to ensure uniqueness */ | |
332 | while (node->parent) { | |
333 | /* | |
334 | * If the address can be translated, then that is as much | |
335 | * uniqueness as we need. Make it the first component and return | |
336 | */ | |
337 | reg = of_get_property(node, "reg", NULL); | |
338 | if (reg && (addr = of_translate_address(node, reg)) != OF_BAD_ADDR) { | |
339 | if (!of_property_read_u32(node, "mask", &mask)) | |
340 | dev_set_name(dev, dev_name(dev) ? "%llx.%x.%pOFn:%s" : "%llx.%x.%pOFn", | |
341 | addr, ffs(mask) - 1, node, dev_name(dev)); | |
342 | ||
343 | else | |
344 | dev_set_name(dev, dev_name(dev) ? "%llx.%pOFn:%s" : "%llx.%pOFn", | |
345 | addr, node, dev_name(dev)); | |
346 | return; | |
347 | } | |
348 | ||
349 | /* format arguments only used if dev_name() resolves to NULL */ | |
350 | dev_set_name(dev, dev_name(dev) ? "%s:%s" : "%s", | |
351 | kbasename(node->full_name), dev_name(dev)); | |
352 | node = node->parent; | |
353 | } | |
354 | } | |
355 | EXPORT_SYMBOL_GPL(of_device_make_bus_id); |