GNU Linux-libre 4.9.309-gnu1
[releases.git] / drivers / staging / fsl-mc / bus / fsl-mc-allocator.c
1 /*
2  * Freescale MC object device allocator driver
3  *
4  * Copyright (C) 2013 Freescale Semiconductor, Inc.
5  *
6  * This file is licensed under the terms of the GNU General Public
7  * License version 2. This program is licensed "as is" without any
8  * warranty of any kind, whether express or implied.
9  */
10
11 #include <linux/module.h>
12 #include <linux/msi.h>
13 #include "../include/mc-bus.h"
14 #include "../include/mc-sys.h"
15 #include "../include/dpbp-cmd.h"
16 #include "../include/dpcon-cmd.h"
17
18 #include "fsl-mc-private.h"
19
20 #define FSL_MC_IS_ALLOCATABLE(_obj_type) \
21         (strcmp(_obj_type, "dpbp") == 0 || \
22          strcmp(_obj_type, "dpmcp") == 0 || \
23          strcmp(_obj_type, "dpcon") == 0)
24
25 /**
26  * fsl_mc_resource_pool_add_device - add allocatable device to a resource
27  * pool of a given MC bus
28  *
29  * @mc_bus: pointer to the MC bus
30  * @pool_type: MC bus pool type
31  * @mc_dev: Pointer to allocatable MC object device
32  *
33  * It adds an allocatable MC object device to a container's resource pool of
34  * the given resource type
35  */
36 static int __must_check fsl_mc_resource_pool_add_device(struct fsl_mc_bus
37                                                                 *mc_bus,
38                                                         enum fsl_mc_pool_type
39                                                                 pool_type,
40                                                         struct fsl_mc_device
41                                                                 *mc_dev)
42 {
43         struct fsl_mc_resource_pool *res_pool;
44         struct fsl_mc_resource *resource;
45         struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
46         int error = -EINVAL;
47
48         if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
49                 goto out;
50         if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
51                 goto out;
52         if (WARN_ON(mc_dev->resource))
53                 goto out;
54
55         res_pool = &mc_bus->resource_pools[pool_type];
56         if (WARN_ON(res_pool->type != pool_type))
57                 goto out;
58         if (WARN_ON(res_pool->mc_bus != mc_bus))
59                 goto out;
60
61         mutex_lock(&res_pool->mutex);
62
63         if (WARN_ON(res_pool->max_count < 0))
64                 goto out_unlock;
65         if (WARN_ON(res_pool->free_count < 0 ||
66                     res_pool->free_count > res_pool->max_count))
67                 goto out_unlock;
68
69         resource = devm_kzalloc(&mc_bus_dev->dev, sizeof(*resource),
70                                 GFP_KERNEL);
71         if (!resource) {
72                 error = -ENOMEM;
73                 dev_err(&mc_bus_dev->dev,
74                         "Failed to allocate memory for fsl_mc_resource\n");
75                 goto out_unlock;
76         }
77
78         resource->type = pool_type;
79         resource->id = mc_dev->obj_desc.id;
80         resource->data = mc_dev;
81         resource->parent_pool = res_pool;
82         INIT_LIST_HEAD(&resource->node);
83         list_add_tail(&resource->node, &res_pool->free_list);
84         mc_dev->resource = resource;
85         res_pool->free_count++;
86         res_pool->max_count++;
87         error = 0;
88 out_unlock:
89         mutex_unlock(&res_pool->mutex);
90 out:
91         return error;
92 }
93
94 /**
95  * fsl_mc_resource_pool_remove_device - remove an allocatable device from a
96  * resource pool
97  *
98  * @mc_dev: Pointer to allocatable MC object device
99  *
100  * It permanently removes an allocatable MC object device from the resource
101  * pool, the device is currently in, as long as it is in the pool's free list.
102  */
103 static int __must_check fsl_mc_resource_pool_remove_device(struct fsl_mc_device
104                                                                    *mc_dev)
105 {
106         struct fsl_mc_device *mc_bus_dev;
107         struct fsl_mc_bus *mc_bus;
108         struct fsl_mc_resource_pool *res_pool;
109         struct fsl_mc_resource *resource;
110         int error = -EINVAL;
111
112         if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
113                 goto out;
114
115         resource = mc_dev->resource;
116         if (WARN_ON(!resource || resource->data != mc_dev))
117                 goto out;
118
119         mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
120         mc_bus = to_fsl_mc_bus(mc_bus_dev);
121         res_pool = resource->parent_pool;
122         if (WARN_ON(res_pool != &mc_bus->resource_pools[resource->type]))
123                 goto out;
124
125         mutex_lock(&res_pool->mutex);
126
127         if (WARN_ON(res_pool->max_count <= 0))
128                 goto out_unlock;
129         if (WARN_ON(res_pool->free_count <= 0 ||
130                     res_pool->free_count > res_pool->max_count))
131                 goto out_unlock;
132
133         /*
134          * If the device is currently allocated, its resource is not
135          * in the free list and thus, the device cannot be removed.
136          */
137         if (list_empty(&resource->node)) {
138                 error = -EBUSY;
139                 dev_err(&mc_bus_dev->dev,
140                         "Device %s cannot be removed from resource pool\n",
141                         dev_name(&mc_dev->dev));
142                 goto out_unlock;
143         }
144
145         list_del_init(&resource->node);
146         res_pool->free_count--;
147         res_pool->max_count--;
148
149         devm_kfree(&mc_bus_dev->dev, resource);
150         mc_dev->resource = NULL;
151         error = 0;
152 out_unlock:
153         mutex_unlock(&res_pool->mutex);
154 out:
155         return error;
156 }
157
158 static const char *const fsl_mc_pool_type_strings[] = {
159         [FSL_MC_POOL_DPMCP] = "dpmcp",
160         [FSL_MC_POOL_DPBP] = "dpbp",
161         [FSL_MC_POOL_DPCON] = "dpcon",
162         [FSL_MC_POOL_IRQ] = "irq",
163 };
164
165 static int __must_check object_type_to_pool_type(const char *object_type,
166                                                  enum fsl_mc_pool_type
167                                                                 *pool_type)
168 {
169         unsigned int i;
170
171         for (i = 0; i < ARRAY_SIZE(fsl_mc_pool_type_strings); i++) {
172                 if (strcmp(object_type, fsl_mc_pool_type_strings[i]) == 0) {
173                         *pool_type = i;
174                         return 0;
175                 }
176         }
177
178         return -EINVAL;
179 }
180
181 int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
182                                           enum fsl_mc_pool_type pool_type,
183                                           struct fsl_mc_resource **new_resource)
184 {
185         struct fsl_mc_resource_pool *res_pool;
186         struct fsl_mc_resource *resource;
187         struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
188         int error = -EINVAL;
189
190         BUILD_BUG_ON(ARRAY_SIZE(fsl_mc_pool_type_strings) !=
191                      FSL_MC_NUM_POOL_TYPES);
192
193         *new_resource = NULL;
194         if (WARN_ON(pool_type < 0 || pool_type >= FSL_MC_NUM_POOL_TYPES))
195                 goto out;
196
197         res_pool = &mc_bus->resource_pools[pool_type];
198         if (WARN_ON(res_pool->mc_bus != mc_bus))
199                 goto out;
200
201         mutex_lock(&res_pool->mutex);
202         resource = list_first_entry_or_null(&res_pool->free_list,
203                                             struct fsl_mc_resource, node);
204
205         if (!resource) {
206                 WARN_ON(res_pool->free_count != 0);
207                 error = -ENXIO;
208                 dev_err(&mc_bus_dev->dev,
209                         "No more resources of type %s left\n",
210                         fsl_mc_pool_type_strings[pool_type]);
211                 goto out_unlock;
212         }
213
214         if (WARN_ON(resource->type != pool_type))
215                 goto out_unlock;
216         if (WARN_ON(resource->parent_pool != res_pool))
217                 goto out_unlock;
218         if (WARN_ON(res_pool->free_count <= 0 ||
219                     res_pool->free_count > res_pool->max_count))
220                 goto out_unlock;
221
222         list_del_init(&resource->node);
223
224         res_pool->free_count--;
225         error = 0;
226 out_unlock:
227         mutex_unlock(&res_pool->mutex);
228         *new_resource = resource;
229 out:
230         return error;
231 }
232 EXPORT_SYMBOL_GPL(fsl_mc_resource_allocate);
233
234 void fsl_mc_resource_free(struct fsl_mc_resource *resource)
235 {
236         struct fsl_mc_resource_pool *res_pool;
237
238         res_pool = resource->parent_pool;
239         if (WARN_ON(resource->type != res_pool->type))
240                 return;
241
242         mutex_lock(&res_pool->mutex);
243         if (WARN_ON(res_pool->free_count < 0 ||
244                     res_pool->free_count >= res_pool->max_count))
245                 goto out_unlock;
246
247         if (WARN_ON(!list_empty(&resource->node)))
248                 goto out_unlock;
249
250         list_add_tail(&resource->node, &res_pool->free_list);
251         res_pool->free_count++;
252 out_unlock:
253         mutex_unlock(&res_pool->mutex);
254 }
255 EXPORT_SYMBOL_GPL(fsl_mc_resource_free);
256
257 /**
258  * fsl_mc_object_allocate - Allocates a MC object device of the given
259  * pool type from a given MC bus
260  *
261  * @mc_dev: MC device for which the MC object device is to be allocated
262  * @pool_type: MC bus resource pool type
263  * @new_mc_dev: Pointer to area where the pointer to the allocated
264  * MC object device is to be returned
265  *
266  * This function allocates a MC object device from the device's parent DPRC,
267  * from the corresponding MC bus' pool of allocatable MC object devices of
268  * the given resource type. mc_dev cannot be a DPRC itself.
269  *
270  * NOTE: pool_type must be different from FSL_MC_POOL_MCP, since MC
271  * portals are allocated using fsl_mc_portal_allocate(), instead of
272  * this function.
273  */
274 int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
275                                         enum fsl_mc_pool_type pool_type,
276                                         struct fsl_mc_device **new_mc_adev)
277 {
278         struct fsl_mc_device *mc_bus_dev;
279         struct fsl_mc_bus *mc_bus;
280         struct fsl_mc_device *mc_adev;
281         int error = -EINVAL;
282         struct fsl_mc_resource *resource = NULL;
283
284         *new_mc_adev = NULL;
285         if (WARN_ON(mc_dev->flags & FSL_MC_IS_DPRC))
286                 goto error;
287
288         if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent)))
289                 goto error;
290
291         if (WARN_ON(pool_type == FSL_MC_POOL_DPMCP))
292                 goto error;
293
294         mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
295         mc_bus = to_fsl_mc_bus(mc_bus_dev);
296         error = fsl_mc_resource_allocate(mc_bus, pool_type, &resource);
297         if (error < 0)
298                 goto error;
299
300         mc_adev = resource->data;
301         if (WARN_ON(!mc_adev))
302                 goto error;
303
304         *new_mc_adev = mc_adev;
305         return 0;
306 error:
307         if (resource)
308                 fsl_mc_resource_free(resource);
309
310         return error;
311 }
312 EXPORT_SYMBOL_GPL(fsl_mc_object_allocate);
313
314 /**
315  * fsl_mc_object_free - Returns an allocatable MC object device to the
316  * corresponding resource pool of a given MC bus.
317  *
318  * @mc_adev: Pointer to the MC object device
319  */
320 void fsl_mc_object_free(struct fsl_mc_device *mc_adev)
321 {
322         struct fsl_mc_resource *resource;
323
324         resource = mc_adev->resource;
325         if (WARN_ON(resource->type == FSL_MC_POOL_DPMCP))
326                 return;
327         if (WARN_ON(resource->data != mc_adev))
328                 return;
329
330         fsl_mc_resource_free(resource);
331 }
332 EXPORT_SYMBOL_GPL(fsl_mc_object_free);
333
334 /*
335  * Initialize the interrupt pool associated with a MC bus.
336  * It allocates a block of IRQs from the GIC-ITS
337  */
338 int fsl_mc_populate_irq_pool(struct fsl_mc_bus *mc_bus,
339                              unsigned int irq_count)
340 {
341         unsigned int i;
342         struct msi_desc *msi_desc;
343         struct fsl_mc_device_irq *irq_resources;
344         struct fsl_mc_device_irq *mc_dev_irq;
345         int error;
346         struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
347         struct fsl_mc_resource_pool *res_pool =
348                         &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
349
350         if (WARN_ON(irq_count == 0 ||
351                     irq_count > FSL_MC_IRQ_POOL_MAX_TOTAL_IRQS))
352                 return -EINVAL;
353
354         error = fsl_mc_msi_domain_alloc_irqs(&mc_bus_dev->dev, irq_count);
355         if (error < 0)
356                 return error;
357
358         irq_resources = devm_kzalloc(&mc_bus_dev->dev,
359                                      sizeof(*irq_resources) * irq_count,
360                                      GFP_KERNEL);
361         if (!irq_resources) {
362                 error = -ENOMEM;
363                 goto cleanup_msi_irqs;
364         }
365
366         for (i = 0; i < irq_count; i++) {
367                 mc_dev_irq = &irq_resources[i];
368
369                 /*
370                  * NOTE: This mc_dev_irq's MSI addr/value pair will be set
371                  * by the fsl_mc_msi_write_msg() callback
372                  */
373                 mc_dev_irq->resource.type = res_pool->type;
374                 mc_dev_irq->resource.data = mc_dev_irq;
375                 mc_dev_irq->resource.parent_pool = res_pool;
376                 INIT_LIST_HEAD(&mc_dev_irq->resource.node);
377                 list_add_tail(&mc_dev_irq->resource.node, &res_pool->free_list);
378         }
379
380         for_each_msi_entry(msi_desc, &mc_bus_dev->dev) {
381                 mc_dev_irq = &irq_resources[msi_desc->fsl_mc.msi_index];
382                 mc_dev_irq->msi_desc = msi_desc;
383                 mc_dev_irq->resource.id = msi_desc->irq;
384         }
385
386         res_pool->max_count = irq_count;
387         res_pool->free_count = irq_count;
388         mc_bus->irq_resources = irq_resources;
389         return 0;
390
391 cleanup_msi_irqs:
392         fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
393         return error;
394 }
395 EXPORT_SYMBOL_GPL(fsl_mc_populate_irq_pool);
396
397 /**
398  * Teardown the interrupt pool associated with an MC bus.
399  * It frees the IRQs that were allocated to the pool, back to the GIC-ITS.
400  */
401 void fsl_mc_cleanup_irq_pool(struct fsl_mc_bus *mc_bus)
402 {
403         struct fsl_mc_device *mc_bus_dev = &mc_bus->mc_dev;
404         struct fsl_mc_resource_pool *res_pool =
405                         &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
406
407         if (WARN_ON(!mc_bus->irq_resources))
408                 return;
409
410         if (WARN_ON(res_pool->max_count == 0))
411                 return;
412
413         if (WARN_ON(res_pool->free_count != res_pool->max_count))
414                 return;
415
416         INIT_LIST_HEAD(&res_pool->free_list);
417         res_pool->max_count = 0;
418         res_pool->free_count = 0;
419         mc_bus->irq_resources = NULL;
420         fsl_mc_msi_domain_free_irqs(&mc_bus_dev->dev);
421 }
422 EXPORT_SYMBOL_GPL(fsl_mc_cleanup_irq_pool);
423
424 /**
425  * It allocates the IRQs required by a given MC object device. The
426  * IRQs are allocated from the interrupt pool associated with the
427  * MC bus that contains the device, if the device is not a DPRC device.
428  * Otherwise, the IRQs are allocated from the interrupt pool associated
429  * with the MC bus that represents the DPRC device itself.
430  */
431 int __must_check fsl_mc_allocate_irqs(struct fsl_mc_device *mc_dev)
432 {
433         int i;
434         int irq_count;
435         int res_allocated_count = 0;
436         int error = -EINVAL;
437         struct fsl_mc_device_irq **irqs = NULL;
438         struct fsl_mc_bus *mc_bus;
439         struct fsl_mc_resource_pool *res_pool;
440
441         if (WARN_ON(mc_dev->irqs))
442                 return -EINVAL;
443
444         irq_count = mc_dev->obj_desc.irq_count;
445         if (WARN_ON(irq_count == 0))
446                 return -EINVAL;
447
448         if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
449                 mc_bus = to_fsl_mc_bus(mc_dev);
450         else
451                 mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
452
453         if (WARN_ON(!mc_bus->irq_resources))
454                 return -EINVAL;
455
456         res_pool = &mc_bus->resource_pools[FSL_MC_POOL_IRQ];
457         if (res_pool->free_count < irq_count) {
458                 dev_err(&mc_dev->dev,
459                         "Not able to allocate %u irqs for device\n", irq_count);
460                 return -ENOSPC;
461         }
462
463         irqs = devm_kzalloc(&mc_dev->dev, irq_count * sizeof(irqs[0]),
464                             GFP_KERNEL);
465         if (!irqs)
466                 return -ENOMEM;
467
468         for (i = 0; i < irq_count; i++) {
469                 struct fsl_mc_resource *resource;
470
471                 error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_IRQ,
472                                                  &resource);
473                 if (error < 0)
474                         goto error_resource_alloc;
475
476                 irqs[i] = to_fsl_mc_irq(resource);
477                 res_allocated_count++;
478
479                 WARN_ON(irqs[i]->mc_dev);
480                 irqs[i]->mc_dev = mc_dev;
481                 irqs[i]->dev_irq_index = i;
482         }
483
484         mc_dev->irqs = irqs;
485         return 0;
486
487 error_resource_alloc:
488         for (i = 0; i < res_allocated_count; i++) {
489                 irqs[i]->mc_dev = NULL;
490                 fsl_mc_resource_free(&irqs[i]->resource);
491         }
492
493         return error;
494 }
495 EXPORT_SYMBOL_GPL(fsl_mc_allocate_irqs);
496
497 /*
498  * It frees the IRQs that were allocated for a MC object device, by
499  * returning them to the corresponding interrupt pool.
500  */
501 void fsl_mc_free_irqs(struct fsl_mc_device *mc_dev)
502 {
503         int i;
504         int irq_count;
505         struct fsl_mc_bus *mc_bus;
506         struct fsl_mc_device_irq **irqs = mc_dev->irqs;
507
508         if (WARN_ON(!irqs))
509                 return;
510
511         irq_count = mc_dev->obj_desc.irq_count;
512
513         if (strcmp(mc_dev->obj_desc.type, "dprc") == 0)
514                 mc_bus = to_fsl_mc_bus(mc_dev);
515         else
516                 mc_bus = to_fsl_mc_bus(to_fsl_mc_device(mc_dev->dev.parent));
517
518         if (WARN_ON(!mc_bus->irq_resources))
519                 return;
520
521         for (i = 0; i < irq_count; i++) {
522                 WARN_ON(!irqs[i]->mc_dev);
523                 irqs[i]->mc_dev = NULL;
524                 fsl_mc_resource_free(&irqs[i]->resource);
525         }
526
527         mc_dev->irqs = NULL;
528 }
529 EXPORT_SYMBOL_GPL(fsl_mc_free_irqs);
530
531 void fsl_mc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
532 {
533         int pool_type;
534         struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
535
536         for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) {
537                 struct fsl_mc_resource_pool *res_pool =
538                     &mc_bus->resource_pools[pool_type];
539
540                 res_pool->type = pool_type;
541                 res_pool->max_count = 0;
542                 res_pool->free_count = 0;
543                 res_pool->mc_bus = mc_bus;
544                 INIT_LIST_HEAD(&res_pool->free_list);
545                 mutex_init(&res_pool->mutex);
546         }
547 }
548
549 static void fsl_mc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
550                                          enum fsl_mc_pool_type pool_type)
551 {
552         struct fsl_mc_resource *resource;
553         struct fsl_mc_resource *next;
554         struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
555         struct fsl_mc_resource_pool *res_pool =
556                                         &mc_bus->resource_pools[pool_type];
557         int free_count = 0;
558
559         WARN_ON(res_pool->type != pool_type);
560         WARN_ON(res_pool->free_count != res_pool->max_count);
561
562         list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
563                 free_count++;
564                 WARN_ON(resource->type != res_pool->type);
565                 WARN_ON(resource->parent_pool != res_pool);
566                 devm_kfree(&mc_bus_dev->dev, resource);
567         }
568
569         WARN_ON(free_count != res_pool->free_count);
570 }
571
572 void fsl_mc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
573 {
574         int pool_type;
575
576         for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++)
577                 fsl_mc_cleanup_resource_pool(mc_bus_dev, pool_type);
578 }
579
580 /**
581  * fsl_mc_allocator_probe - callback invoked when an allocatable device is
582  * being added to the system
583  */
584 static int fsl_mc_allocator_probe(struct fsl_mc_device *mc_dev)
585 {
586         enum fsl_mc_pool_type pool_type;
587         struct fsl_mc_device *mc_bus_dev;
588         struct fsl_mc_bus *mc_bus;
589         int error;
590
591         if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
592                 return -EINVAL;
593
594         mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
595         if (WARN_ON(!dev_is_fsl_mc(&mc_bus_dev->dev)))
596                 return -EINVAL;
597
598         mc_bus = to_fsl_mc_bus(mc_bus_dev);
599         error = object_type_to_pool_type(mc_dev->obj_desc.type, &pool_type);
600         if (error < 0)
601                 return error;
602
603         error = fsl_mc_resource_pool_add_device(mc_bus, pool_type, mc_dev);
604         if (error < 0)
605                 return error;
606
607         dev_dbg(&mc_dev->dev,
608                 "Allocatable MC object device bound to fsl_mc_allocator driver");
609         return 0;
610 }
611
612 /**
613  * fsl_mc_allocator_remove - callback invoked when an allocatable device is
614  * being removed from the system
615  */
616 static int fsl_mc_allocator_remove(struct fsl_mc_device *mc_dev)
617 {
618         int error;
619
620         if (WARN_ON(!FSL_MC_IS_ALLOCATABLE(mc_dev->obj_desc.type)))
621                 return -EINVAL;
622
623         if (mc_dev->resource) {
624                 error = fsl_mc_resource_pool_remove_device(mc_dev);
625                 if (error < 0)
626                         return error;
627         }
628
629         dev_dbg(&mc_dev->dev,
630                 "Allocatable MC object device unbound from fsl_mc_allocator driver");
631         return 0;
632 }
633
634 static const struct fsl_mc_device_id match_id_table[] = {
635         {
636          .vendor = FSL_MC_VENDOR_FREESCALE,
637          .obj_type = "dpbp",
638         },
639         {
640          .vendor = FSL_MC_VENDOR_FREESCALE,
641          .obj_type = "dpmcp",
642         },
643         {
644          .vendor = FSL_MC_VENDOR_FREESCALE,
645          .obj_type = "dpcon",
646         },
647         {.vendor = 0x0},
648 };
649
650 static struct fsl_mc_driver fsl_mc_allocator_driver = {
651         .driver = {
652                    .name = "fsl_mc_allocator",
653                    .pm = NULL,
654                    },
655         .match_id_table = match_id_table,
656         .probe = fsl_mc_allocator_probe,
657         .remove = fsl_mc_allocator_remove,
658 };
659
660 int __init fsl_mc_allocator_driver_init(void)
661 {
662         return fsl_mc_driver_register(&fsl_mc_allocator_driver);
663 }
664
665 void fsl_mc_allocator_driver_exit(void)
666 {
667         fsl_mc_driver_unregister(&fsl_mc_allocator_driver);
668 }