Skip to content

Commit

Permalink
mmc: sdhci-of-arasan: Add support for dynamic configuration
Browse files Browse the repository at this point in the history
Add support for dynamic configuration which will takes care of
configuring the SD secure space configuration registers using EEMI APIs,
performing SD reset assert and deassert.
High level sequence:
- Check for the PM dynamic configuration support, if no error proceed with
SD dynamic configurations(next steps) otherwise skip the dynamic
configuration.
- Put the SD Controller in reset.
- Configure SD Fixed configurations.
- Configure the SD Slot Type.
- Configure the BASE_CLOCK.
- Configure the 8-bit support.
- Bring the SD Controller out of reset.

In the above steps, apart from the Fixed configurations, remaining all
configurations are dynamic and they will be read from devicetree during
driver probe.

Signed-off-by: Sai Krishna Potthuri <lakshmi.sai.krishna.potthuri@xilinx.com>
  • Loading branch information
Sai Krishna Potthuri authored and Michal Simek committed Jan 31, 2022
1 parent aa65f3d commit 3c7719d
Showing 1 changed file with 55 additions and 0 deletions.
55 changes: 55 additions & 0 deletions drivers/mmc/host/sdhci-of-arasan.c
Expand Up @@ -21,6 +21,7 @@
#include <linux/of_device.h>
#include <linux/phy/phy.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/of.h>
#include <linux/firmware/xlnx-zynqmp.h>

Expand Down Expand Up @@ -1495,6 +1496,51 @@ static int sdhci_arasan_register_sdclk(struct sdhci_arasan_data *sdhci_arasan,
return 0;
}

static int sdhci_zynqmp_set_dynamic_config(struct device *dev,
struct sdhci_arasan_data *sdhci_arasan)
{
struct sdhci_host *host = sdhci_arasan->host;
struct clk_hw *hw = &sdhci_arasan->clk_data.sdcardclk_hw;
struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
const char *clk_name = clk_hw_get_name(hw);
u32 node_id = !strcmp(clk_name, "clk_out_sd0") ? NODE_SD_0 : NODE_SD_1;
struct reset_control *rstc;
u32 mhz;
int ret;

/* Obtain SDHC reset control */
rstc = devm_reset_control_get_optional_exclusive(dev, NULL);
if (IS_ERR(rstc)) {
dev_err(dev, "Cannot get SDHC reset.\n");
return PTR_ERR(rstc);
}

reset_control_assert(rstc);

ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_FIXED, 0);
if (ret)
return ret;

ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_EMMC_SEL,
!!(host->mmc->caps & MMC_CAP_NONREMOVABLE));
if (ret)
return ret;

mhz = DIV_ROUND_CLOSEST_ULL(clk_get_rate(pltfm_host->clk), 1000000);
ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_BASECLK, mhz);
if (ret)
return ret;

ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_8BIT,
!!(host->mmc->caps & MMC_CAP_8_BIT_DATA));
if (ret)
return ret;

reset_control_deassert(rstc);

return 0;
}

static int sdhci_arasan_add_host(struct sdhci_arasan_data *sdhci_arasan)
{
struct sdhci_host *host = sdhci_arasan->host;
Expand Down Expand Up @@ -1655,6 +1701,15 @@ static int sdhci_arasan_probe(struct platform_device *pdev)
goto unreg_clk;
}

if (of_device_is_compatible(np, "xlnx,zynqmp-8.9a")) {
ret = zynqmp_pm_is_function_supported(PM_IOCTL, IOCTL_SET_SD_CONFIG);
if (!ret) {
ret = sdhci_zynqmp_set_dynamic_config(dev, sdhci_arasan);
if (ret)
goto unreg_clk;
}
}

sdhci_arasan->phy = ERR_PTR(-ENODEV);
if (of_device_is_compatible(np, "arasan,sdhci-5.1")) {
sdhci_arasan->phy = devm_phy_get(dev, "phy_arasan");
Expand Down

0 comments on commit 3c7719d

Please sign in to comment.