/** * dprc_add_new_devices - Adds devices to the logical bus for a DPRC * * @mc_bus_dev: pointer to the fsl-mc device that represents a DPRC object * @obj_desc_array: array of device descriptors for child devices currently * present in the physical DPRC. * @num_child_objects_in_mc: number of entries in obj_desc_array * * Synchronizes the state of the Linux bus driver with the actual * state of the MC by adding objects that have been newly discovered * in the physical DPRC. */ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev, struct dprc_obj_desc *obj_desc_array, int num_child_objects_in_mc) { int error; int i; for (i = 0; i < num_child_objects_in_mc; i++) { struct fsl_mc_device *child_dev; struct dprc_obj_desc *obj_desc = &obj_desc_array[i]; if (strlen(obj_desc->type) == 0) continue; /* * Check if device is already known to Linux: */ child_dev = fsl_mc_device_lookup(obj_desc, mc_bus_dev); if (child_dev) { check_plugged_state_change(child_dev, obj_desc); continue; } error = fsl_mc_device_add(obj_desc, NULL, &mc_bus_dev->dev, &child_dev); if (error < 0) continue; } }
/** * fsl_mc_bus_probe - callback invoked when the root MC bus is being * added */ static int fsl_mc_bus_probe(struct platform_device *pdev) { struct dprc_obj_desc obj_desc; int error; struct fsl_mc *mc; struct fsl_mc_device *mc_bus_dev = NULL; struct fsl_mc_io *mc_io = NULL; int container_id; phys_addr_t mc_portal_phys_addr; u32 mc_portal_size; struct mc_version mc_version; struct resource res; dev_info(&pdev->dev, "Root MC bus device probed"); mc = devm_kzalloc(&pdev->dev, sizeof(*mc), GFP_KERNEL); if (!mc) return -ENOMEM; platform_set_drvdata(pdev, mc); /* * Get physical address of MC portal for the root DPRC: */ error = of_address_to_resource(pdev->dev.of_node, 0, &res); if (error < 0) { dev_err(&pdev->dev, "of_address_to_resource() failed for %s\n", pdev->dev.of_node->full_name); return error; } mc_portal_phys_addr = res.start; mc_portal_size = resource_size(&res); error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr, mc_portal_size, NULL, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io); if (error < 0) return error; error = mc_get_version(mc_io, 0, &mc_version); if (error != 0) { dev_err(&pdev->dev, "mc_get_version() failed with error %d\n", error); goto error_cleanup_mc_io; } dev_info(&pdev->dev, "Freescale Management Complex Firmware version: %u.%u.%u\n", mc_version.major, mc_version.minor, mc_version.revision); if (mc_version.major < MC_VER_MAJOR) { dev_err(&pdev->dev, "ERROR: MC firmware version not supported by driver (driver version: %u.%u)\n", MC_VER_MAJOR, MC_VER_MINOR); error = -ENOTSUPP; goto error_cleanup_mc_io; } if (mc_version.major > MC_VER_MAJOR) { dev_warn(&pdev->dev, "WARNING: driver may not support newer MC firmware features (driver version: %u.%u)\n", MC_VER_MAJOR, MC_VER_MINOR); } error = get_mc_addr_translation_ranges(&pdev->dev, &mc->translation_ranges, &mc->num_translation_ranges); if (error < 0) goto error_cleanup_mc_io; error = dpmng_get_container_id(mc_io, 0, &container_id); if (error < 0) { dev_err(&pdev->dev, "dpmng_get_container_id() failed: %d\n", error); goto error_cleanup_mc_io; } obj_desc.vendor = FSL_MC_VENDOR_FREESCALE; strcpy(obj_desc.type, "dprc"); obj_desc.id = container_id; obj_desc.ver_major = DPRC_VER_MAJOR; obj_desc.ver_minor = DPRC_VER_MINOR; obj_desc.irq_count = 1; obj_desc.region_count = 0; error = fsl_mc_device_add(&obj_desc, mc_io, &pdev->dev, &mc_bus_dev); if (error < 0) goto error_cleanup_mc_io; mc->root_mc_bus_dev = mc_bus_dev; return 0; error_cleanup_mc_io: fsl_destroy_mc_io(mc_io); return error; }