Broadcom BCM2712 SDHCI controller is SD Express capable. Add support
for sde capability where the implementation is based on downstream driver,
diverging from it in the way that init_sd_express callback is invoked:
in downstream the sdhci_ops structure has been augmented with a new
function ptr 'init_sd_express' that just propagate the call to the
driver specific callback so that the callstack from a structure
standpoint is mmc_host_ops -> sdhci_ops. The drawback here is in the
added level of indirection (the newly added init_sd_express is
redundant) and the sdhci_ops structure declaration has to be changed.
To overcome this the presented approach consist in patching the mmc_host_ops
init_sd_express callback to point directly to the custom function defined in
this driver (see struct brcmstb_match_priv).
Signed-off-by: Andrea della Porta <andrea.porta-IBi9RG/b67k@xxxxxxxxxxxxxxxx>
---
drivers/mmc/host/Kconfig | 1 +
drivers/mmc/host/sdhci-brcmstb.c | 147 ++++++++++++++++++++++++++++++-
2 files changed, 147 insertions(+), 1 deletion(-)
+ if (brcmstb_priv->sde_pcie) {
+ struct of_changeset changeset;
+ static struct property okay_property = {
+ .name = "status",
+ .value = "okay",
+ .length = 5,
+ };
+
+ /* Enable the pcie controller */
+ of_changeset_init(&changeset);
+ ret = of_changeset_update_property(&changeset,
+ brcmstb_priv->sde_pcie,
+ &okay_property);
+ if (ret) {
+ dev_err(dev, "%s: failed to update property - %d\n", __func__,
+ ret);
+ return -ENODEV;
+ }
+ ret = of_changeset_apply(&changeset);
+ }
+
+ dev_dbg(dev, "%s -> %d\n", __func__, ret);
+ return ret;
+}
+
@@ -468,6 +581,24 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
if (res)
goto err;
+ priv->sde_1v8 = devm_regulator_get_optional(&pdev->dev, "sde-1v8");
+ if (IS_ERR(priv->sde_1v8))
+ priv->flags &= ~BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS;
+
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+ if (iomem) {
+ priv->sde_ioaddr = devm_ioremap_resource(&pdev->dev, iomem);
+ if (IS_ERR(priv->sde_ioaddr))
+ priv->sde_ioaddr = NULL;
+ }
+
+ iomem = platform_get_resource(pdev, IORESOURCE_MEM, 3);
+ if (iomem) {
+ priv->sde_ioaddr2 = devm_ioremap_resource(&pdev->dev, iomem);
+ if (IS_ERR(priv->sde_ioaddr2))
+ priv->sde_ioaddr = NULL;
+ }
+
priv->pinctrl = devm_pinctrl_get(&pdev->dev);
if (IS_ERR(priv->pinctrl)) {
no_pinctrl = true;
@@ -478,8 +609,16 @@ static int sdhci_brcmstb_probe(struct platform_device *pdev)
no_pinctrl = true;
}
- if (no_pinctrl )
+ priv->pins_sdex = pinctrl_lookup_state(priv->pinctrl, "sd-express");
+ if (IS_ERR(priv->pins_sdex)) {
+ dev_dbg(&pdev->dev, "No pinctrl sd-express state\n");
+ no_pinctrl = true;
+ }
+
+ if (no_pinctrl || !priv->sde_ioaddr || !priv->sde_ioaddr2) {
priv->pinctrl = NULL;
+ priv->flags &= ~BRCMSTB_PRIV_FLAGS_HAS_SD_EXPRESS;
+ }
/*
* Automatic clock gating does not work for SD cards that may