#include <linux/delay.h>
#include "mmc_private.h"
#include <log.h>
+#include <reset.h>
#include <dm/device_compat.h>
#include <linux/err.h>
#include <linux/libfdt.h>
+#include <asm/types.h>
+#include <linux/math64.h>
#include <asm/cache.h>
#include <malloc.h>
#include <sdhci.h>
u8 deviceid;
u8 bank;
u8 no_1p8;
+ struct reset_ctl_bulk resets;
};
/* For Versal platforms zynqmp_mmio_write() won't be available */
char tuning_loop_counter = SDHCI_TUNING_LOOP_COUNT;
u8 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
- debug("%s\n", __func__);
+ dev_dbg(mmc->dev, "%s\n", __func__);
host = priv->host;
};
#endif
+#if defined(CONFIG_ARCH_ZYNQMP)
+static int sdhci_zynqmp_set_dynamic_config(struct arasan_sdhci_priv *priv,
+ struct udevice *dev)
+{
+ int ret;
+ u32 node_id = priv->deviceid ? NODE_SD_1 : NODE_SD_0;
+ struct clk clk;
+ unsigned long clock, mhz;
+
+ ret = xilinx_pm_request(PM_REQUEST_NODE, node_id, ZYNQMP_PM_CAPABILITY_ACCESS,
+ ZYNQMP_PM_MAX_QOS, ZYNQMP_PM_REQUEST_ACK_NO, NULL);
+ if (ret) {
+ dev_err(dev, "Request node failed for %d\n", node_id);
+ return ret;
+ }
+
+ ret = reset_get_bulk(dev, &priv->resets);
+ if (ret == -ENOTSUPP || ret == -ENOENT) {
+ dev_err(dev, "Reset not found\n");
+ return 0;
+ } else if (ret) {
+ dev_err(dev, "Reset failed\n");
+ return ret;
+ }
+
+ ret = reset_assert_bulk(&priv->resets);
+ if (ret) {
+ dev_err(dev, "Reset assert failed\n");
+ return ret;
+ }
+
+ ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_FIXED, 0);
+ if (ret) {
+ dev_err(dev, "SD_CONFIG_FIXED failed\n");
+ return ret;
+ }
+
+ ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_EMMC_SEL,
+ dev_read_bool(dev, "non-removable"));
+ if (ret) {
+ dev_err(dev, "SD_CONFIG_EMMC_SEL failed\n");
+ return ret;
+ }
+
+ ret = clk_get_by_index(dev, 0, &clk);
+ if (ret < 0) {
+ dev_err(dev, "failed to get clock\n");
+ return ret;
+ }
+
+ clock = clk_get_rate(&clk);
+ if (IS_ERR_VALUE(clock)) {
+ dev_err(dev, "failed to get rate\n");
+ return clock;
+ }
+
+ mhz = DIV64_U64_ROUND_UP(clock, 1000000);
+
+ ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_BASECLK, mhz);
+ if (ret) {
+ dev_err(dev, "SD_CONFIG_BASECLK failed\n");
+ return ret;
+ }
+
+ ret = zynqmp_pm_set_sd_config(node_id, SD_CONFIG_8BIT,
+ (dev_read_u32_default(dev, "bus-width", 1) == 8));
+ if (ret) {
+ dev_err(dev, "SD_CONFIG_8BIT failed\n");
+ return ret;
+ }
+
+ ret = reset_deassert_bulk(&priv->resets);
+ if (ret) {
+ dev_err(dev, "Reset release failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+#endif
+
static int arasan_sdhci_probe(struct udevice *dev)
{
struct arasan_sdhci_plat *plat = dev_get_plat(dev);
host = priv->host;
+#if defined(CONFIG_ARCH_ZYNQMP)
+ if (device_is_compatible(dev, "xlnx,zynqmp-8.9a")) {
+ ret = zynqmp_pm_is_function_supported(PM_IOCTL,
+ IOCTL_SET_SD_CONFIG);
+ if (!ret) {
+ ret = sdhci_zynqmp_set_dynamic_config(priv, dev);
+ if (ret)
+ return ret;
+ }
+ }
+#endif
+
ret = clk_get_by_index(dev, 0, &clk);
if (ret < 0) {
dev_err(dev, "failed to get clock\n");
return clock;
}
- debug("%s: CLK %ld\n", __func__, clock);
+ dev_dbg(dev, "%s: CLK %ld\n", __func__, clock);
ret = clk_enable(&clk);
if (ret) {