diff --git a/drivers/mfd/bcm2835-pm.c b/drivers/mfd/bcm2835-pm.c index 42fe67f1538e76887e0ddfc631724e72a119ef72..ab1e9cbc50b1b0d9a12406647ac3742b8eddebab 100644 --- a/drivers/mfd/bcm2835-pm.c +++ b/drivers/mfd/bcm2835-pm.c @@ -50,6 +50,17 @@ static int bcm2835_pm_probe(struct platform_device *pdev) if (ret) return ret; + /* Map the ARGON ASB regs if present. */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 2); + if (res) { + pm->arg_asb = devm_ioremap_resource(dev, res); + if (IS_ERR(pm->arg_asb)) { + dev_err(dev, "Failed to map ARGON ASB: %ld\n", + PTR_ERR(pm->arg_asb)); + return PTR_ERR(pm->arg_asb); + } + } + /* We'll use the presence of the AXI ASB regs in the * bcm2835-pm binding as the key for whether we can reference * the full PM register range and support power domains. diff --git a/drivers/soc/bcm/bcm2835-power.c b/drivers/soc/bcm/bcm2835-power.c index 1e0041ec813238cbfa7ab52c3fdc9799961169d1..c0618a9c26fac2e090f483314f2117d86a92824f 100644 --- a/drivers/soc/bcm/bcm2835-power.c +++ b/drivers/soc/bcm/bcm2835-power.c @@ -143,6 +143,8 @@ struct bcm2835_power { /* AXI Async bridge registers. */ void __iomem *asb; + bool is_2711; + struct genpd_onecell_data pd_xlate; struct bcm2835_power_domain domains[BCM2835_POWER_DOMAIN_COUNT]; struct reset_controller_dev reset; @@ -192,6 +194,10 @@ static int bcm2835_power_power_off(struct bcm2835_power_domain *pd, u32 pm_reg) { struct bcm2835_power *power = pd->power; + /* 2711 has no power domains above the reset controller. */ + if (power->is_2711) + return 0; + /* Enable functional isolation */ PM_WRITE(pm_reg, PM_READ(pm_reg) & ~PM_ISFUNC); @@ -213,6 +219,10 @@ static int bcm2835_power_power_on(struct bcm2835_power_domain *pd, u32 pm_reg) int inrush; bool powok; + /* 2711 has no power domains above the reset controller. */ + if (power->is_2711) + return 0; + /* If it was already powered on by the fw, leave it that way. */ if (PM_READ(pm_reg) & PM_POWUP) return 0; @@ -627,6 +637,18 @@ static int bcm2835_power_probe(struct platform_device *pdev) power->base = pm->base; power->asb = pm->asb; + /* 2711 hack: the new ARGON ASB took over V3D, which is our + * only consumer of this driver so far. The old ASB seems to + * still be present with ISP and H264 bits but no V3D, but I + * don't know if that's real or not. The V3D is in the same + * place in the new ASB as the old one, so just poke the new + * one for now. + */ + if (pm->arg_asb) { + power->asb = pm->arg_asb; + power->is_2711 = true; + } + id = ASB_READ(ASB_AXI_BRDG_ID); if (id != 0x62726467 /* "BRDG" */) { dev_err(dev, "ASB register ID returned 0x%08x\n", id); diff --git a/include/linux/mfd/bcm2835-pm.h b/include/linux/mfd/bcm2835-pm.h index ed37dc40e82a821a990cc4442c61d8a8b6842c0f..b2d157091e12bdb4cb30f751867946e63d99b632 100644 --- a/include/linux/mfd/bcm2835-pm.h +++ b/include/linux/mfd/bcm2835-pm.h @@ -9,6 +9,7 @@ struct bcm2835_pm { struct device *dev; void __iomem *base; void __iomem *asb; + void __iomem *arg_asb; }; #endif /* BCM2835_MFD_PM_H */