]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/staging/fsl-mc/bus/mc-bus.c
Merge tag 'omap-for-v4.7-dts-fixes1' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / drivers / staging / fsl-mc / bus / mc-bus.c
1 /*
2  * Freescale Management Complex (MC) bus driver
3  *
4  * Copyright (C) 2014 Freescale Semiconductor, Inc.
5  * Author: German Rivera <German.Rivera@freescale.com>
6  *
7  * This file is licensed under the terms of the GNU General Public
8  * License version 2. This program is licensed "as is" without any
9  * warranty of any kind, whether express or implied.
10  */
11
12 #include "../include/mc-private.h"
13 #include <linux/module.h>
14 #include <linux/of_device.h>
15 #include <linux/of_address.h>
16 #include <linux/ioport.h>
17 #include <linux/slab.h>
18 #include <linux/limits.h>
19 #include <linux/bitops.h>
20 #include <linux/msi.h>
21 #include "../include/dpmng.h"
22 #include "../include/mc-sys.h"
23 #include "dprc-cmd.h"
24
25 static struct kmem_cache *mc_dev_cache;
26
27 static bool fsl_mc_is_root_dprc(struct device *dev);
28
29 /**
30  * fsl_mc_bus_match - device to driver matching callback
31  * @dev: the MC object device structure to match against
32  * @drv: the device driver to search for matching MC object device id
33  * structures
34  *
35  * Returns 1 on success, 0 otherwise.
36  */
37 static int fsl_mc_bus_match(struct device *dev, struct device_driver *drv)
38 {
39         const struct fsl_mc_device_match_id *id;
40         struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
41         struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(drv);
42         bool found = false;
43
44         if (WARN_ON(!fsl_mc_bus_exists()))
45                 goto out;
46
47         if (!mc_drv->match_id_table)
48                 goto out;
49
50         /*
51          * If the object is not 'plugged' don't match.
52          * Only exception is the root DPRC, which is a special case.
53          */
54         if ((mc_dev->obj_desc.state & DPRC_OBJ_STATE_PLUGGED) == 0 &&
55             !fsl_mc_is_root_dprc(&mc_dev->dev))
56                 goto out;
57
58         /*
59          * Traverse the match_id table of the given driver, trying to find
60          * a matching for the given MC object device.
61          */
62         for (id = mc_drv->match_id_table; id->vendor != 0x0; id++) {
63                 if (id->vendor == mc_dev->obj_desc.vendor &&
64                     strcmp(id->obj_type, mc_dev->obj_desc.type) == 0) {
65                         found = true;
66
67                         break;
68                 }
69         }
70
71 out:
72         dev_dbg(dev, "%smatched\n", found ? "" : "not ");
73         return found;
74 }
75
76 /**
77  * fsl_mc_bus_uevent - callback invoked when a device is added
78  */
79 static int fsl_mc_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
80 {
81         pr_debug("%s invoked\n", __func__);
82         return 0;
83 }
84
85 struct bus_type fsl_mc_bus_type = {
86         .name = "fsl-mc",
87         .match = fsl_mc_bus_match,
88         .uevent = fsl_mc_bus_uevent,
89 };
90 EXPORT_SYMBOL_GPL(fsl_mc_bus_type);
91
92 static atomic_t root_dprc_count = ATOMIC_INIT(0);
93
94 static int fsl_mc_driver_probe(struct device *dev)
95 {
96         struct fsl_mc_driver *mc_drv;
97         struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
98         int error;
99
100         if (WARN_ON(!dev->driver))
101                 return -EINVAL;
102
103         mc_drv = to_fsl_mc_driver(dev->driver);
104         if (WARN_ON(!mc_drv->probe))
105                 return -EINVAL;
106
107         error = mc_drv->probe(mc_dev);
108         if (error < 0) {
109                 dev_err(dev, "MC object device probe callback failed: %d\n",
110                         error);
111                 return error;
112         }
113
114         return 0;
115 }
116
117 static int fsl_mc_driver_remove(struct device *dev)
118 {
119         struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
120         struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
121         int error;
122
123         if (WARN_ON(!dev->driver))
124                 return -EINVAL;
125
126         error = mc_drv->remove(mc_dev);
127         if (error < 0) {
128                 dev_err(dev,
129                         "MC object device remove callback failed: %d\n",
130                         error);
131                 return error;
132         }
133
134         return 0;
135 }
136
137 static void fsl_mc_driver_shutdown(struct device *dev)
138 {
139         struct fsl_mc_driver *mc_drv = to_fsl_mc_driver(dev->driver);
140         struct fsl_mc_device *mc_dev = to_fsl_mc_device(dev);
141
142         mc_drv->shutdown(mc_dev);
143 }
144
145 /**
146  * __fsl_mc_driver_register - registers a child device driver with the
147  * MC bus
148  *
149  * This function is implicitly invoked from the registration function of
150  * fsl_mc device drivers, which is generated by the
151  * module_fsl_mc_driver() macro.
152  */
153 int __fsl_mc_driver_register(struct fsl_mc_driver *mc_driver,
154                              struct module *owner)
155 {
156         int error;
157
158         mc_driver->driver.owner = owner;
159         mc_driver->driver.bus = &fsl_mc_bus_type;
160
161         if (mc_driver->probe)
162                 mc_driver->driver.probe = fsl_mc_driver_probe;
163
164         if (mc_driver->remove)
165                 mc_driver->driver.remove = fsl_mc_driver_remove;
166
167         if (mc_driver->shutdown)
168                 mc_driver->driver.shutdown = fsl_mc_driver_shutdown;
169
170         error = driver_register(&mc_driver->driver);
171         if (error < 0) {
172                 pr_err("driver_register() failed for %s: %d\n",
173                        mc_driver->driver.name, error);
174                 return error;
175         }
176
177         pr_info("MC object device driver %s registered\n",
178                 mc_driver->driver.name);
179         return 0;
180 }
181 EXPORT_SYMBOL_GPL(__fsl_mc_driver_register);
182
183 /**
184  * fsl_mc_driver_unregister - unregisters a device driver from the
185  * MC bus
186  */
187 void fsl_mc_driver_unregister(struct fsl_mc_driver *mc_driver)
188 {
189         driver_unregister(&mc_driver->driver);
190 }
191 EXPORT_SYMBOL_GPL(fsl_mc_driver_unregister);
192
193 /**
194  * fsl_mc_bus_exists - check if a root dprc exists
195  */
196 bool fsl_mc_bus_exists(void)
197 {
198         return atomic_read(&root_dprc_count) > 0;
199 }
200 EXPORT_SYMBOL_GPL(fsl_mc_bus_exists);
201
202 /**
203 * fsl_mc_get_root_dprc - function to traverse to the root dprc
204 */
205 static void fsl_mc_get_root_dprc(struct device *dev,
206                                  struct device **root_dprc_dev)
207 {
208         if (WARN_ON(!dev)) {
209                 *root_dprc_dev = NULL;
210         } else if (WARN_ON(dev->bus != &fsl_mc_bus_type)) {
211                 *root_dprc_dev = NULL;
212         } else {
213                 *root_dprc_dev = dev;
214                 while ((*root_dprc_dev)->parent->bus == &fsl_mc_bus_type)
215                         *root_dprc_dev = (*root_dprc_dev)->parent;
216         }
217 }
218
219 /**
220  * fsl_mc_is_root_dprc - function to check if a given device is a root dprc
221  */
222 static bool fsl_mc_is_root_dprc(struct device *dev)
223 {
224         struct device *root_dprc_dev;
225
226         fsl_mc_get_root_dprc(dev, &root_dprc_dev);
227         if (!root_dprc_dev)
228                 return false;
229         return dev == root_dprc_dev;
230 }
231
232 static int get_dprc_attr(struct fsl_mc_io *mc_io,
233                          int container_id, struct dprc_attributes *attr)
234 {
235         u16 dprc_handle;
236         int error;
237
238         error = dprc_open(mc_io, 0, container_id, &dprc_handle);
239         if (error < 0) {
240                 dev_err(mc_io->dev, "dprc_open() failed: %d\n", error);
241                 return error;
242         }
243
244         memset(attr, 0, sizeof(struct dprc_attributes));
245         error = dprc_get_attributes(mc_io, 0, dprc_handle, attr);
246         if (error < 0) {
247                 dev_err(mc_io->dev, "dprc_get_attributes() failed: %d\n",
248                         error);
249                 goto common_cleanup;
250         }
251
252         error = 0;
253
254 common_cleanup:
255         (void)dprc_close(mc_io, 0, dprc_handle);
256         return error;
257 }
258
259 static int get_dprc_icid(struct fsl_mc_io *mc_io,
260                          int container_id, u16 *icid)
261 {
262         struct dprc_attributes attr;
263         int error;
264
265         error = get_dprc_attr(mc_io, container_id, &attr);
266         if (error == 0)
267                 *icid = attr.icid;
268
269         return error;
270 }
271
272 static int get_dprc_version(struct fsl_mc_io *mc_io,
273                             int container_id, u16 *major, u16 *minor)
274 {
275         struct dprc_attributes attr;
276         int error;
277
278         error = get_dprc_attr(mc_io, container_id, &attr);
279         if (error == 0) {
280                 *major = attr.version.major;
281                 *minor = attr.version.minor;
282         }
283
284         return error;
285 }
286
287 static int translate_mc_addr(struct fsl_mc_device *mc_dev,
288                              enum dprc_region_type mc_region_type,
289                              u64 mc_offset, phys_addr_t *phys_addr)
290 {
291         int i;
292         struct device *root_dprc_dev;
293         struct fsl_mc *mc;
294
295         fsl_mc_get_root_dprc(&mc_dev->dev, &root_dprc_dev);
296         if (WARN_ON(!root_dprc_dev))
297                 return -EINVAL;
298         mc = dev_get_drvdata(root_dprc_dev->parent);
299
300         if (mc->num_translation_ranges == 0) {
301                 /*
302                  * Do identity mapping:
303                  */
304                 *phys_addr = mc_offset;
305                 return 0;
306         }
307
308         for (i = 0; i < mc->num_translation_ranges; i++) {
309                 struct fsl_mc_addr_translation_range *range =
310                         &mc->translation_ranges[i];
311
312                 if (mc_region_type == range->mc_region_type &&
313                     mc_offset >= range->start_mc_offset &&
314                     mc_offset < range->end_mc_offset) {
315                         *phys_addr = range->start_phys_addr +
316                                      (mc_offset - range->start_mc_offset);
317                         return 0;
318                 }
319         }
320
321         return -EFAULT;
322 }
323
324 static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
325                                           struct fsl_mc_device *mc_bus_dev)
326 {
327         int i;
328         int error;
329         struct resource *regions;
330         struct dprc_obj_desc *obj_desc = &mc_dev->obj_desc;
331         struct device *parent_dev = mc_dev->dev.parent;
332         enum dprc_region_type mc_region_type;
333
334         if (strcmp(obj_desc->type, "dprc") == 0 ||
335             strcmp(obj_desc->type, "dpmcp") == 0) {
336                 mc_region_type = DPRC_REGION_TYPE_MC_PORTAL;
337         } else if (strcmp(obj_desc->type, "dpio") == 0) {
338                 mc_region_type = DPRC_REGION_TYPE_QBMAN_PORTAL;
339         } else {
340                 /*
341                  * This function should not have been called for this MC object
342                  * type, as this object type is not supposed to have MMIO
343                  * regions
344                  */
345                 WARN_ON(true);
346                 return -EINVAL;
347         }
348
349         regions = kmalloc_array(obj_desc->region_count,
350                                 sizeof(regions[0]), GFP_KERNEL);
351         if (!regions)
352                 return -ENOMEM;
353
354         for (i = 0; i < obj_desc->region_count; i++) {
355                 struct dprc_region_desc region_desc;
356
357                 error = dprc_get_obj_region(mc_bus_dev->mc_io,
358                                             0,
359                                             mc_bus_dev->mc_handle,
360                                             obj_desc->type,
361                                             obj_desc->id, i, &region_desc);
362                 if (error < 0) {
363                         dev_err(parent_dev,
364                                 "dprc_get_obj_region() failed: %d\n", error);
365                         goto error_cleanup_regions;
366                 }
367
368                 WARN_ON(region_desc.size == 0);
369                 error = translate_mc_addr(mc_dev, mc_region_type,
370                                           region_desc.base_offset,
371                                           &regions[i].start);
372                 if (error < 0) {
373                         dev_err(parent_dev,
374                                 "Invalid MC offset: %#x (for %s.%d\'s region %d)\n",
375                                 region_desc.base_offset,
376                                 obj_desc->type, obj_desc->id, i);
377                         goto error_cleanup_regions;
378                 }
379
380                 regions[i].end = regions[i].start + region_desc.size - 1;
381                 regions[i].name = "fsl-mc object MMIO region";
382                 regions[i].flags = IORESOURCE_IO;
383                 if (region_desc.flags & DPRC_REGION_CACHEABLE)
384                         regions[i].flags |= IORESOURCE_CACHEABLE;
385         }
386
387         mc_dev->regions = regions;
388         return 0;
389
390 error_cleanup_regions:
391         kfree(regions);
392         return error;
393 }
394
395 /**
396  * Add a newly discovered MC object device to be visible in Linux
397  */
398 int fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
399                       struct fsl_mc_io *mc_io,
400                       struct device *parent_dev,
401                       struct fsl_mc_device **new_mc_dev)
402 {
403         int error;
404         struct fsl_mc_device *mc_dev = NULL;
405         struct fsl_mc_bus *mc_bus = NULL;
406         struct fsl_mc_device *parent_mc_dev;
407
408         if (parent_dev->bus == &fsl_mc_bus_type)
409                 parent_mc_dev = to_fsl_mc_device(parent_dev);
410         else
411                 parent_mc_dev = NULL;
412
413         if (strcmp(obj_desc->type, "dprc") == 0) {
414                 /*
415                  * Allocate an MC bus device object:
416                  */
417                 mc_bus = devm_kzalloc(parent_dev, sizeof(*mc_bus), GFP_KERNEL);
418                 if (!mc_bus)
419                         return -ENOMEM;
420
421                 mc_dev = &mc_bus->mc_dev;
422         } else {
423                 /*
424                  * Allocate a regular fsl_mc_device object:
425                  */
426                 mc_dev = kmem_cache_zalloc(mc_dev_cache, GFP_KERNEL);
427                 if (!mc_dev)
428                         return -ENOMEM;
429         }
430
431         mc_dev->obj_desc = *obj_desc;
432         mc_dev->mc_io = mc_io;
433         device_initialize(&mc_dev->dev);
434         mc_dev->dev.parent = parent_dev;
435         mc_dev->dev.bus = &fsl_mc_bus_type;
436         dev_set_name(&mc_dev->dev, "%s.%d", obj_desc->type, obj_desc->id);
437
438         if (strcmp(obj_desc->type, "dprc") == 0) {
439                 struct fsl_mc_io *mc_io2;
440
441                 mc_dev->flags |= FSL_MC_IS_DPRC;
442
443                 /*
444                  * To get the DPRC's ICID, we need to open the DPRC
445                  * in get_dprc_icid(). For child DPRCs, we do so using the
446                  * parent DPRC's MC portal instead of the child DPRC's MC
447                  * portal, in case the child DPRC is already opened with
448                  * its own portal (e.g., the DPRC used by AIOP).
449                  *
450                  * NOTE: There cannot be more than one active open for a
451                  * given MC object, using the same MC portal.
452                  */
453                 if (parent_mc_dev) {
454                         /*
455                          * device being added is a child DPRC device
456                          */
457                         mc_io2 = parent_mc_dev->mc_io;
458                 } else {
459                         /*
460                          * device being added is the root DPRC device
461                          */
462                         if (WARN_ON(!mc_io)) {
463                                 error = -EINVAL;
464                                 goto error_cleanup_dev;
465                         }
466
467                         mc_io2 = mc_io;
468
469                         atomic_inc(&root_dprc_count);
470                 }
471
472                 error = get_dprc_icid(mc_io2, obj_desc->id, &mc_dev->icid);
473                 if (error < 0)
474                         goto error_cleanup_dev;
475         } else {
476                 /*
477                  * A non-DPRC MC object device has to be a child of another
478                  * MC object (specifically a DPRC object)
479                  */
480                 mc_dev->icid = parent_mc_dev->icid;
481                 mc_dev->dma_mask = FSL_MC_DEFAULT_DMA_MASK;
482                 mc_dev->dev.dma_mask = &mc_dev->dma_mask;
483                 dev_set_msi_domain(&mc_dev->dev,
484                                    dev_get_msi_domain(&parent_mc_dev->dev));
485         }
486
487         /*
488          * Get MMIO regions for the device from the MC:
489          *
490          * NOTE: the root DPRC is a special case as its MMIO region is
491          * obtained from the device tree
492          */
493         if (parent_mc_dev && obj_desc->region_count != 0) {
494                 error = fsl_mc_device_get_mmio_regions(mc_dev,
495                                                        parent_mc_dev);
496                 if (error < 0)
497                         goto error_cleanup_dev;
498         }
499
500         /* Objects are coherent, unless 'no shareability' flag set. */
501         if (!(obj_desc->flags & DPRC_OBJ_FLAG_NO_MEM_SHAREABILITY))
502                 arch_setup_dma_ops(&mc_dev->dev, 0, 0, NULL, true);
503
504         /*
505          * The device-specific probe callback will get invoked by device_add()
506          */
507         error = device_add(&mc_dev->dev);
508         if (error < 0) {
509                 dev_err(parent_dev,
510                         "device_add() failed for device %s: %d\n",
511                         dev_name(&mc_dev->dev), error);
512                 goto error_cleanup_dev;
513         }
514
515         (void)get_device(&mc_dev->dev);
516         dev_dbg(parent_dev, "Added MC object device %s\n",
517                 dev_name(&mc_dev->dev));
518
519         *new_mc_dev = mc_dev;
520         return 0;
521
522 error_cleanup_dev:
523         kfree(mc_dev->regions);
524         if (mc_bus)
525                 devm_kfree(parent_dev, mc_bus);
526         else
527                 kmem_cache_free(mc_dev_cache, mc_dev);
528
529         return error;
530 }
531 EXPORT_SYMBOL_GPL(fsl_mc_device_add);
532
533 /**
534  * fsl_mc_device_remove - Remove a MC object device from being visible to
535  * Linux
536  *
537  * @mc_dev: Pointer to a MC object device object
538  */
539 void fsl_mc_device_remove(struct fsl_mc_device *mc_dev)
540 {
541         struct fsl_mc_bus *mc_bus = NULL;
542
543         kfree(mc_dev->regions);
544
545         /*
546          * The device-specific remove callback will get invoked by device_del()
547          */
548         device_del(&mc_dev->dev);
549         put_device(&mc_dev->dev);
550
551         if (strcmp(mc_dev->obj_desc.type, "dprc") == 0) {
552                 mc_bus = to_fsl_mc_bus(mc_dev);
553                 if (mc_dev->mc_io) {
554                         fsl_destroy_mc_io(mc_dev->mc_io);
555                         mc_dev->mc_io = NULL;
556                 }
557
558                 if (fsl_mc_is_root_dprc(&mc_dev->dev)) {
559                         if (atomic_read(&root_dprc_count) > 0)
560                                 atomic_dec(&root_dprc_count);
561                         else
562                                 WARN_ON(1);
563                 }
564         }
565
566         if (mc_bus)
567                 devm_kfree(mc_dev->dev.parent, mc_bus);
568         else
569                 kmem_cache_free(mc_dev_cache, mc_dev);
570 }
571 EXPORT_SYMBOL_GPL(fsl_mc_device_remove);
572
573 static int parse_mc_ranges(struct device *dev,
574                            int *paddr_cells,
575                            int *mc_addr_cells,
576                            int *mc_size_cells,
577                            const __be32 **ranges_start,
578                            u8 *num_ranges)
579 {
580         const __be32 *prop;
581         int range_tuple_cell_count;
582         int ranges_len;
583         int tuple_len;
584         struct device_node *mc_node = dev->of_node;
585
586         *ranges_start = of_get_property(mc_node, "ranges", &ranges_len);
587         if (!(*ranges_start) || !ranges_len) {
588                 dev_warn(dev,
589                          "missing or empty ranges property for device tree node '%s'\n",
590                          mc_node->name);
591
592                 *num_ranges = 0;
593                 return 0;
594         }
595
596         *paddr_cells = of_n_addr_cells(mc_node);
597
598         prop = of_get_property(mc_node, "#address-cells", NULL);
599         if (prop)
600                 *mc_addr_cells = be32_to_cpup(prop);
601         else
602                 *mc_addr_cells = *paddr_cells;
603
604         prop = of_get_property(mc_node, "#size-cells", NULL);
605         if (prop)
606                 *mc_size_cells = be32_to_cpup(prop);
607         else
608                 *mc_size_cells = of_n_size_cells(mc_node);
609
610         range_tuple_cell_count = *paddr_cells + *mc_addr_cells +
611                                  *mc_size_cells;
612
613         tuple_len = range_tuple_cell_count * sizeof(__be32);
614         if (ranges_len % tuple_len != 0) {
615                 dev_err(dev, "malformed ranges property '%s'\n", mc_node->name);
616                 return -EINVAL;
617         }
618
619         *num_ranges = ranges_len / tuple_len;
620         return 0;
621 }
622
623 static int get_mc_addr_translation_ranges(struct device *dev,
624                                           struct fsl_mc_addr_translation_range
625                                                 **ranges,
626                                           u8 *num_ranges)
627 {
628         int error;
629         int paddr_cells;
630         int mc_addr_cells;
631         int mc_size_cells;
632         int i;
633         const __be32 *ranges_start;
634         const __be32 *cell;
635
636         error = parse_mc_ranges(dev,
637                                 &paddr_cells,
638                                 &mc_addr_cells,
639                                 &mc_size_cells,
640                                 &ranges_start,
641                                 num_ranges);
642         if (error < 0)
643                 return error;
644
645         if (!(*num_ranges)) {
646                 /*
647                  * Missing or empty ranges property ("ranges;") for the
648                  * 'fsl,qoriq-mc' node. In this case, identity mapping
649                  * will be used.
650                  */
651                 *ranges = NULL;
652                 return 0;
653         }
654
655         *ranges = devm_kcalloc(dev, *num_ranges,
656                                sizeof(struct fsl_mc_addr_translation_range),
657                                GFP_KERNEL);
658         if (!(*ranges))
659                 return -ENOMEM;
660
661         cell = ranges_start;
662         for (i = 0; i < *num_ranges; ++i) {
663                 struct fsl_mc_addr_translation_range *range = &(*ranges)[i];
664
665                 range->mc_region_type = of_read_number(cell, 1);
666                 range->start_mc_offset = of_read_number(cell + 1,
667                                                         mc_addr_cells - 1);
668                 cell += mc_addr_cells;
669                 range->start_phys_addr = of_read_number(cell, paddr_cells);
670                 cell += paddr_cells;
671                 range->end_mc_offset = range->start_mc_offset +
672                                      of_read_number(cell, mc_size_cells);
673
674                 cell += mc_size_cells;
675         }
676
677         return 0;
678 }
679
680 /**
681  * fsl_mc_bus_probe - callback invoked when the root MC bus is being
682  * added
683  */
684 static int fsl_mc_bus_probe(struct platform_device *pdev)
685 {
686         struct dprc_obj_desc obj_desc;
687         int error;
688         struct fsl_mc *mc;
689         struct fsl_mc_device *mc_bus_dev = NULL;
690         struct fsl_mc_io *mc_io = NULL;
691         int container_id;
692         phys_addr_t mc_portal_phys_addr;
693         u32 mc_portal_size;
694         struct mc_version mc_version;
695         struct resource res;
696
697         dev_info(&pdev->dev, "Root MC bus device probed");
698
699         mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL);
700         if (!mc)
701                 return -ENOMEM;
702
703         platform_set_drvdata(pdev, mc);
704
705         /*
706          * Get physical address of MC portal for the root DPRC:
707          */
708         error = of_address_to_resource(pdev->dev.of_node, 0, &res);
709         if (error < 0) {
710                 dev_err(&pdev->dev,
711                         "of_address_to_resource() failed for %s\n",
712                         pdev->dev.of_node->full_name);
713                 return error;
714         }
715
716         mc_portal_phys_addr = res.start;
717         mc_portal_size = resource_size(&res);
718         error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr,
719                                  mc_portal_size, NULL,
720                                  FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io);
721         if (error < 0)
722                 return error;
723
724         error = mc_get_version(mc_io, 0, &mc_version);
725         if (error != 0) {
726                 dev_err(&pdev->dev,
727                         "mc_get_version() failed with error %d\n", error);
728                 goto error_cleanup_mc_io;
729         }
730
731         dev_info(&pdev->dev,
732                  "Freescale Management Complex Firmware version: %u.%u.%u\n",
733                  mc_version.major, mc_version.minor, mc_version.revision);
734
735         error = get_mc_addr_translation_ranges(&pdev->dev,
736                                                &mc->translation_ranges,
737                                                &mc->num_translation_ranges);
738         if (error < 0)
739                 goto error_cleanup_mc_io;
740
741         error = dpmng_get_container_id(mc_io, 0, &container_id);
742         if (error < 0) {
743                 dev_err(&pdev->dev,
744                         "dpmng_get_container_id() failed: %d\n", error);
745                 goto error_cleanup_mc_io;
746         }
747
748         memset(&obj_desc, 0, sizeof(struct dprc_obj_desc));
749         error = get_dprc_version(mc_io, container_id,
750                                  &obj_desc.ver_major, &obj_desc.ver_minor);
751         if (error < 0)
752                 goto error_cleanup_mc_io;
753
754         obj_desc.vendor = FSL_MC_VENDOR_FREESCALE;
755         strcpy(obj_desc.type, "dprc");
756         obj_desc.id = container_id;
757         obj_desc.irq_count = 1;
758         obj_desc.region_count = 0;
759
760         error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, &mc_bus_dev);
761         if (error < 0)
762                 goto error_cleanup_mc_io;
763
764         mc->root_mc_bus_dev = mc_bus_dev;
765         return 0;
766
767 error_cleanup_mc_io:
768         fsl_destroy_mc_io(mc_io);
769         return error;
770 }
771
772 /**
773  * fsl_mc_bus_remove - callback invoked when the root MC bus is being
774  * removed
775  */
776 static int fsl_mc_bus_remove(struct platform_device *pdev)
777 {
778         struct fsl_mc *mc = platform_get_drvdata(pdev);
779
780         if (WARN_ON(!fsl_mc_is_root_dprc(&mc->root_mc_bus_dev->dev)))
781                 return -EINVAL;
782
783         fsl_mc_device_remove(mc->root_mc_bus_dev);
784         dev_info(&pdev->dev, "Root MC bus device removed");
785         return 0;
786 }
787
788 static const struct of_device_id fsl_mc_bus_match_table[] = {
789         {.compatible = "fsl,qoriq-mc",},
790         {},
791 };
792
793 MODULE_DEVICE_TABLE(of, fsl_mc_bus_match_table);
794
795 static struct platform_driver fsl_mc_bus_driver = {
796         .driver = {
797                    .name = "fsl_mc_bus",
798                    .pm = NULL,
799                    .of_match_table = fsl_mc_bus_match_table,
800                    },
801         .probe = fsl_mc_bus_probe,
802         .remove = fsl_mc_bus_remove,
803 };
804
805 static int __init fsl_mc_bus_driver_init(void)
806 {
807         int error;
808
809         mc_dev_cache = kmem_cache_create("fsl_mc_device",
810                                          sizeof(struct fsl_mc_device), 0, 0,
811                                          NULL);
812         if (!mc_dev_cache) {
813                 pr_err("Could not create fsl_mc_device cache\n");
814                 return -ENOMEM;
815         }
816
817         error = bus_register(&fsl_mc_bus_type);
818         if (error < 0) {
819                 pr_err("fsl-mc bus type registration failed: %d\n", error);
820                 goto error_cleanup_cache;
821         }
822
823         pr_info("fsl-mc bus type registered\n");
824
825         error = platform_driver_register(&fsl_mc_bus_driver);
826         if (error < 0) {
827                 pr_err("platform_driver_register() failed: %d\n", error);
828                 goto error_cleanup_bus;
829         }
830
831         error = dprc_driver_init();
832         if (error < 0)
833                 goto error_cleanup_driver;
834
835         error = fsl_mc_allocator_driver_init();
836         if (error < 0)
837                 goto error_cleanup_dprc_driver;
838
839         error = its_fsl_mc_msi_init();
840         if (error < 0)
841                 goto error_cleanup_mc_allocator;
842
843         return 0;
844
845 error_cleanup_mc_allocator:
846         fsl_mc_allocator_driver_exit();
847
848 error_cleanup_dprc_driver:
849         dprc_driver_exit();
850
851 error_cleanup_driver:
852         platform_driver_unregister(&fsl_mc_bus_driver);
853
854 error_cleanup_bus:
855         bus_unregister(&fsl_mc_bus_type);
856
857 error_cleanup_cache:
858         kmem_cache_destroy(mc_dev_cache);
859         return error;
860 }
861
862 postcore_initcall(fsl_mc_bus_driver_init);
863
864 static void __exit fsl_mc_bus_driver_exit(void)
865 {
866         if (WARN_ON(!mc_dev_cache))
867                 return;
868
869         its_fsl_mc_msi_cleanup();
870         fsl_mc_allocator_driver_exit();
871         dprc_driver_exit();
872         platform_driver_unregister(&fsl_mc_bus_driver);
873         bus_unregister(&fsl_mc_bus_type);
874         kmem_cache_destroy(mc_dev_cache);
875         pr_info("MC bus unregistered\n");
876 }
877
878 module_exit(fsl_mc_bus_driver_exit);
879
880 MODULE_AUTHOR("Freescale Semiconductor Inc.");
881 MODULE_DESCRIPTION("Freescale Management Complex (MC) bus driver");
882 MODULE_LICENSE("GPL");