Commit 0614b0ae authored by Sai Krishna Potthuri's avatar Sai Krishna Potthuri Committed by Ulf Hansson

mmc: sdhci-of-arasan: Add support for dynamic configuration

Add dynamic configuration support for Xilinx ZynqMP which 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.
- Wait for 1msec delay.
Signed-off-by: default avatarSai Krishna Potthuri <sai.krishna.potthuri@amd.com>
Acked-by: default avatarMichal Simek <michal.simek@amd.com>
Link: https://lore.kernel.org/r/20221019054857.8286-1-sai.krishna.potthuri@amd.comSigned-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent 24e961b9
......@@ -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>
......@@ -1522,6 +1523,65 @@ 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 mhz, node_id = !strcmp(clk_name, "clk_out_sd0") ? NODE_SD_0 : NODE_SD_1;
struct reset_control *rstc;
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);
}
ret = reset_control_assert(rstc);
if (ret)
return ret;
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);
if (mhz > 100 && mhz <= 200)
mhz = 200;
else if (mhz > 50 && mhz <= 100)
mhz = 100;
else if (mhz > 25 && mhz <= 50)
mhz = 50;
else
mhz = 25;
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;
ret = reset_control_deassert(rstc);
if (ret)
return ret;
usleep_range(1000, 1500);
return 0;
}
static int sdhci_arasan_add_host(struct sdhci_arasan_data *sdhci_arasan)
{
struct sdhci_host *host = sdhci_arasan->host;
......@@ -1686,6 +1746,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");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment