1
2
3
4
5
6
7
8#include <linux/bitmap.h>
9#include <linux/device.h>
10#include <linux/firmware/xlnx-zynqmp.h>
11#include <linux/kernel.h>
12#include <linux/list.h>
13#include <linux/mutex.h>
14#include <linux/of.h>
15#include <linux/of_address.h>
16#include <linux/of_device.h>
17#include <linux/of_irq.h>
18#include <uapi/linux/xlnx-ai-engine.h>
19
20#include "ai-engine-internal.h"
21
22
23#define XAIE_DMA_BIT_MASK 48U
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40unsigned int aie_aperture_get_num_parts(struct aie_aperture *aperture)
41{
42 struct aie_partition *apart;
43 int ret;
44 unsigned int rs, re, num_parts = 0;
45
46 ret = mutex_lock_interruptible(&aperture->mlock);
47 if (ret)
48 return ret;
49
50 list_for_each_entry(apart, &aperture->partitions, node) {
51 num_parts++;
52 }
53
54 bitmap_for_each_clear_region(aperture->cols_res.bitmap, rs, re, 0,
55 (aperture->range.size.col - 1)) {
56 num_parts++;
57 }
58
59 mutex_unlock(&aperture->mlock);
60
61 return num_parts;
62}
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81int aie_aperture_enquire_parts(struct aie_aperture *aperture,
82 unsigned int num_queries,
83 struct aie_range_args *queries,
84 int *num_parts_left, bool to_user)
85{
86 struct aie_partition *apart;
87 int ret;
88 unsigned int rs, re, num_queries_left;
89
90 *num_parts_left = 0;
91 num_queries_left = num_queries;
92 ret = mutex_lock_interruptible(&aperture->mlock);
93 if (ret)
94 return ret;
95
96 list_for_each_entry(apart, &aperture->partitions, node) {
97 struct aie_range_args query;
98
99 if (!num_queries_left) {
100 *num_parts_left += 1;
101 continue;
102 }
103 query.partition_id = apart->range.start.col <<
104 AIE_PART_ID_START_COL_SHIFT;
105 query.partition_id += apart->range.size.col <<
106 AIE_PART_ID_NUM_COLS_SHIFT;
107 query.range.start.col = apart->range.start.col;
108 query.range.size.col = apart->range.size.col;
109 query.range.start.row = apart->range.start.row;
110 query.range.size.row = apart->range.size.row;
111 query.status = apart->status;
112
113 if (to_user) {
114 if (copy_to_user((void __user *)queries, &query,
115 sizeof(query))) {
116 mutex_unlock(&aperture->mlock);
117 return -EFAULT;
118 }
119 } else {
120 memcpy(queries, &query, sizeof(query));
121 }
122 queries++;
123 num_queries_left--;
124 }
125
126 bitmap_for_each_clear_region(aperture->cols_res.bitmap, rs, re, 0,
127 (aperture->range.size.col - 1)) {
128 struct aie_range_args query;
129
130 if (!num_queries_left) {
131 *num_parts_left += 1;
132 continue;
133 }
134 query.partition_id = (rs & AIE_PART_ID_START_COL_MASK) <<
135 AIE_PART_ID_START_COL_SHIFT;
136 query.partition_id += ((re - rs + 1) &
137 AIE_PART_ID_NUM_COLS_MASK) <<
138 AIE_PART_ID_NUM_COLS_SHIFT;
139 query.range.start.col = rs;
140 query.range.size.col = re - rs + 1;
141 query.range.start.row = aperture->range.start.row;
142 query.range.size.row = aperture->range.size.row;
143 query.status = 0;
144
145 if (to_user) {
146 if (copy_to_user((void __user *)queries, &query,
147 sizeof(query))) {
148 mutex_unlock(&aperture->mlock);
149 return -EFAULT;
150 }
151 } else {
152 memcpy(queries, &query, sizeof(query));
153 }
154 queries++;
155 num_queries_left--;
156 }
157
158 mutex_unlock(&aperture->mlock);
159
160 return (num_queries - num_queries_left);
161}
162
163
164
165
166
167
168
169
170
171
172struct aie_partition *
173aie_aperture_request_part_from_id(struct aie_aperture *aperture,
174 u32 partition_id)
175{
176 struct aie_partition *apart = NULL;
177 u32 in_partition_id = partition_id;
178 u8 start_col, num_cols;
179 int ret;
180
181 start_col = aie_part_id_get_start_col(partition_id);
182 num_cols = aie_part_id_get_num_cols(partition_id);
183
184
185
186
187
188 if (num_cols == 0) {
189 start_col = aperture->range.start.col;
190 num_cols = aperture->range.size.col;
191 partition_id = ((u32)start_col << AIE_PART_ID_START_COL_SHIFT) |
192 ((u32)num_cols << AIE_PART_ID_NUM_COLS_SHIFT);
193 }
194
195 if (start_col < aperture->range.start.col ||
196 num_cols > aperture->range.size.col ||
197 (start_col + num_cols) >
198 (aperture->range.start.col + aperture->range.size.col)) {
199 dev_err(&aperture->dev, "invalid partition %u: %u,%u.\n",
200 partition_id, start_col, num_cols);
201 return ERR_PTR(-EINVAL);
202 }
203
204 ret = mutex_lock_interruptible(&aperture->mlock);
205 if (ret)
206 return ERR_PTR(ret);
207
208 ret = aie_resource_get_region(&aperture->cols_res, start_col, num_cols);
209 if (ret != (u32)start_col) {
210 dev_err(&aperture->dev, "partition %u already requested.\n",
211 in_partition_id);
212 mutex_unlock(&aperture->mlock);
213 return ERR_PTR(-EINVAL);
214 }
215
216 apart = aie_create_partition(aperture, partition_id);
217 if (IS_ERR(apart)) {
218 dev_err(&aperture->dev, "failed to create partition %u.\n",
219 partition_id);
220 mutex_unlock(&aperture->mlock);
221 return apart;
222 }
223
224 list_add_tail(&apart->node, &aperture->partitions);
225
226 mutex_unlock(&aperture->mlock);
227
228 return apart;
229}
230
231
232
233
234
235
236
237
238
239
240
241int aie_aperture_check_part_avail(struct aie_aperture *aperture,
242 struct aie_partition_req *req)
243{
244 unsigned int start_col, end_col, num_cols;
245
246 start_col = aie_part_id_get_start_col(req->partition_id);
247 num_cols = aie_part_id_get_num_cols(req->partition_id);
248
249
250
251
252
253 if (num_cols == 0) {
254 start_col = aperture->range.start.col;
255 num_cols = aperture->range.size.col;
256 }
257
258 end_col = start_col + num_cols - 1;
259
260 if (start_col < aperture->range.start.col ||
261 end_col >= aperture->range.start.col + aperture->range.size.col) {
262 return XAIE_PART_STATUS_INVALID;
263 }
264
265 if (aie_resource_check_region(&aperture->cols_res, start_col,
266 num_cols) < 0)
267 return XAIE_PART_STATUS_INUSE;
268
269 return XAIE_PART_STATUS_IDLE;
270}
271
272
273
274
275
276
277
278
279static void aie_aperture_release_device(struct device *dev)
280{
281 struct aie_aperture *aperture = dev_get_drvdata(dev);
282
283 aie_resource_uninitialize(&aperture->cols_res);
284 aie_resource_uninitialize(&aperture->l2_mask);
285 zynqmp_pm_release_node(aperture->node_id);
286 kfree(aperture);
287}
288
289
290
291
292
293
294
295
296int aie_aperture_remove(struct aie_aperture *aperture)
297{
298 struct list_head *node, *pos;
299 int ret;
300
301 ret = mutex_lock_interruptible(&aperture->mlock);
302 if (ret)
303 return ret;
304
305 list_for_each_safe(pos, node, &aperture->partitions) {
306 struct aie_partition *apart;
307
308 apart = list_entry(pos, struct aie_partition, node);
309 list_del(&apart->node);
310 aie_part_remove(apart);
311 }
312 mutex_unlock(&aperture->mlock);
313
314 of_node_clear_flag(aperture->dev.of_node, OF_POPULATED);
315 device_del(&aperture->dev);
316 put_device(&aperture->dev);
317
318 return 0;
319}
320
321
322
323
324
325
326
327
328
329
330
331
332int aie_aperture_add_dev(struct aie_aperture *aperture,
333 struct device_node *nc)
334{
335 struct device *dev = &aperture->dev;
336
337
338 dev = &aperture->dev;
339 dev->class = aie_class;
340 dev->parent = &aperture->adev->dev;
341 dev->of_node = nc;
342 dev->driver_data = aperture;
343 dev_set_name(dev, "aieaperture_%u_%u", aperture->range.start.col,
344 aperture->range.size.col);
345
346 dev->release = aie_aperture_release_device;
347
348 return device_register(&aperture->dev);
349}
350
351
352
353
354
355
356
357
358
359
360
361struct aie_aperture *
362of_aie_aperture_probe(struct aie_device *adev, struct device_node *nc)
363{
364 struct aie_aperture *aperture, *laperture;
365 struct device *dev;
366 struct aie_range *range;
367 u32 regs[2];
368 int ret;
369
370 aperture = kzalloc(sizeof(*aperture), GFP_KERNEL);
371 if (!aperture)
372 return ERR_PTR(-ENOMEM);
373
374 aperture->adev = adev;
375 INIT_LIST_HEAD(&aperture->partitions);
376 mutex_init(&aperture->mlock);
377
378 range = &aperture->range;
379 ret = of_property_read_u32_array(nc, "xlnx,columns", regs,
380 ARRAY_SIZE(regs));
381 if (ret < 0) {
382 dev_err(&adev->dev,
383 "probe %pOF failed, no tiles range information.\n",
384 nc);
385 goto free_aperture;
386 }
387 range->start.col = regs[0] & aligned_byte_mask(1);
388 range->size.col = regs[1] & aligned_byte_mask(1);
389
390
391
392
393
394 range->start.row = 0;
395 range->size.row = adev->ttype_attr[AIE_TILE_TYPE_SHIMPL].num_rows +
396 adev->ttype_attr[AIE_TILE_TYPE_MEMORY].num_rows +
397 adev->ttype_attr[AIE_TILE_TYPE_TILE].num_rows;
398
399 ret = of_property_read_u32_index(nc, "xlnx,node-id", 0,
400 &aperture->node_id);
401 if (ret < 0) {
402 dev_err(&adev->dev,
403 "probe %pOF failed, no aperture node id.\n", nc);
404 goto free_aperture;
405 }
406
407
408 list_for_each_entry(laperture, &adev->apertures, node) {
409 u32 start_col, end_col, check_start_col, check_end_col;
410
411 if (laperture->node_id == aperture->node_id) {
412 dev_err(&adev->dev,
413 "probe failed, aperture %u exists.\n",
414 aperture->node_id);
415 ret = -EINVAL;
416 goto free_aperture;
417 }
418
419 start_col = range->start.col;
420 end_col = start_col + range->size.col - 1;
421 check_start_col = laperture->range.start.col;
422 check_end_col = check_start_col + laperture->range.size.col - 1;
423 if ((start_col >= check_start_col &&
424 start_col <= check_end_col) ||
425 (end_col >= check_start_col &&
426 end_col <= check_end_col)) {
427 dev_err(&adev->dev,
428 "probe failed, aperture %u overlaps other aperture.\n",
429 aperture->node_id);
430 ret = -EINVAL;
431 goto free_aperture;
432 }
433 }
434
435
436 ret = aie_aperture_add_dev(aperture, nc);
437 if (ret) {
438 dev_err(&aperture->dev, "device_add failed: %d\n", ret);
439 goto free_aperture;
440 }
441 dev = &aperture->dev;
442
443
444
445
446
447 ret = aie_resource_initialize(&aperture->cols_res,
448 aperture->range.size.col);
449 if (ret) {
450 dev_err(dev, "failed to initialize columns resource.\n");
451 goto put_aperture_dev;
452 }
453
454 ret = of_address_to_resource(nc, 0, &aperture->res);
455 if (ret < 0) {
456 dev_err(dev, "failed to get address from device node.\n");
457 goto put_aperture_dev;
458 }
459 aperture->base = devm_ioremap_resource(dev, &aperture->res);
460 if (!aperture->base) {
461 ret = -ENOMEM;
462 goto put_aperture_dev;
463 }
464
465
466 dev->coherent_dma_mask = DMA_BIT_MASK(XAIE_DMA_BIT_MASK);
467 dev->dma_mask = &dev->coherent_dma_mask;
468 ret = of_dma_configure(&aperture->dev, nc, true);
469 if (ret)
470 dev_warn(&aperture->dev, "Failed to configure DMA.\n");
471
472
473 ret = of_irq_get_byname(nc, "interrupt1");
474 if (ret < 0) {
475 dev_warn(dev, "no interrupt in device node.");
476 } else {
477 aperture->irq = ret;
478 INIT_WORK(&aperture->backtrack, aie_aperture_backtrack);
479 ret = aie_aperture_create_l2_bitmap(aperture);
480 if (ret) {
481 dev_err(dev,
482 "failed to initialize l2 mask resource.\n");
483 goto put_aperture_dev;
484 }
485
486 ret = devm_request_threaded_irq(dev, aperture->irq, NULL,
487 aie_interrupt, IRQF_ONESHOT,
488 dev_name(dev), aperture);
489 if (ret) {
490 dev_err(dev, "Failed to request AIE IRQ.\n");
491 goto put_aperture_dev;
492 }
493 }
494
495 ret = zynqmp_pm_request_node(aperture->node_id,
496 ZYNQMP_PM_CAPABILITY_ACCESS, 0,
497 ZYNQMP_PM_REQUEST_ACK_BLOCKING);
498 if (ret < 0) {
499 dev_err(dev, "Unable to request node %d\n", aperture->node_id);
500 goto put_aperture_dev;
501 }
502
503 of_node_get(nc);
504
505 dev_info(dev,
506 "AI engine aperture %s, id 0x%x, cols(%u, %u) aie_tile_rows(%u, %u) memory_tile_rows(%u, %u) is probed successfully.\n",
507 dev_name(dev), aperture->node_id,
508 aperture->range.start.col, aperture->range.size.col,
509 adev->ttype_attr[AIE_TILE_TYPE_TILE].start_row,
510 adev->ttype_attr[AIE_TILE_TYPE_TILE].num_rows,
511 adev->ttype_attr[AIE_TILE_TYPE_MEMORY].start_row,
512 adev->ttype_attr[AIE_TILE_TYPE_MEMORY].num_rows);
513
514 return aperture;
515
516put_aperture_dev:
517 put_device(dev);
518 return ERR_PTR(ret);
519
520free_aperture:
521 kfree(aperture);
522 return ERR_PTR(ret);
523}
524