bus: fsl-mc: fix mmio base address for child DPRCs
authorLaurentiu Tudor <laurentiu.tudor@nxp.com>
Thu, 15 Jul 2021 14:07:18 +0000 (17:07 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 21 Jul 2021 11:56:25 +0000 (13:56 +0200)
Some versions of the MC firmware wrongly report 0 for register base
address of the DPMCP associated with child DPRC objects thus rendering
them unusable. This is particularly troublesome in ACPI boot scenarios
where the legacy way of extracting this base address from the device
tree does not apply.
Given that DPMCPs share the same base address, workaround this by using
the base address extracted from the root DPRC container.

Signed-off-by: Laurentiu Tudor <laurentiu.tudor@nxp.com>
Link: https://lore.kernel.org/r/20210715140718.8513-8-laurentiu.tudor@nxp.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/bus/fsl-mc/fsl-mc-bus.c

index 3159501..6273f78 100644 (file)
@@ -69,6 +69,8 @@ struct fsl_mc_addr_translation_range {
 #define MC_FAPR_PL     BIT(18)
 #define MC_FAPR_BMT    BIT(17)
 
+static phys_addr_t mc_portal_base_phys_addr;
+
 /**
  * fsl_mc_bus_match - device to driver matching callback
  * @dev: the fsl-mc device to match against
@@ -704,14 +706,30 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev,
                 * If base address is in the region_desc use it otherwise
                 * revert to old mechanism
                 */
-               if (region_desc.base_address)
+               if (region_desc.base_address) {
                        regions[i].start = region_desc.base_address +
                                                region_desc.base_offset;
-               else
+               } else {
                        error = translate_mc_addr(mc_dev, mc_region_type,
                                          region_desc.base_offset,
                                          &regions[i].start);
 
+                       /*
+                        * Some versions of the MC firmware wrongly report
+                        * 0 for register base address of the DPMCP associated
+                        * with child DPRC objects thus rendering them unusable.
+                        * This is particularly troublesome in ACPI boot
+                        * scenarios where the legacy way of extracting this
+                        * base address from the device tree does not apply.
+                        * Given that DPMCPs share the same base address,
+                        * workaround this by using the base address extracted
+                        * from the root DPRC container.
+                        */
+                       if (is_fsl_mc_bus_dprc(mc_dev) &&
+                           regions[i].start == region_desc.base_offset)
+                               regions[i].start += mc_portal_base_phys_addr;
+               }
+
                if (error < 0) {
                        dev_err(parent_dev,
                                "Invalid MC offset: %#x (for %s.%d\'s region %d)\n",
@@ -1150,6 +1168,8 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
        plat_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        mc_portal_phys_addr = plat_res->start;
        mc_portal_size = resource_size(plat_res);
+       mc_portal_base_phys_addr = mc_portal_phys_addr & ~0x3ffffff;
+
        error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr,
                                 mc_portal_size, NULL,
                                 FSL_MC_IO_ATOMIC_CONTEXT_PORTAL, &mc_io);