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