@@ -5,16 +5,17 @@
#include <common.h>
#include <asm/arch/clock_manager.h>
-#include <asm/arch/system_manager.h>
#include <clk.h>
#include <dm.h>
#include <dwmmc.h>
#include <errno.h>
#include <fdtdec.h>
+#include <hang.h>
#include <dm/device_compat.h>
#include <linux/libfdt.h>
#include <linux/err.h>
#include <malloc.h>
+#include <misc.h>
#include <reset.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -24,6 +25,13 @@ struct socfpga_dwmci_plat {
struct mmc mmc;
};
+/* System Manager's SDMMC CCLK phase shift register */
+struct sysmgr_sdmmc_reg {
+ u32 offset;
+ u32 drvsel_shift;
+ u32 smplsel_shift;
+};
+
/* socfpga implmentation specific driver private data */
struct dwmci_socfpga_priv_data {
struct dwmci_host host;
@@ -45,11 +53,54 @@ static void socfpga_dwmci_reset(struct udevice *dev)
reset_deassert_bulk(&reset_bulk);
}
+static int get_sysmgr_sdmmc_reg(struct udevice *dev,
+ struct sysmgr_sdmmc_reg *reg)
+{
+ struct ofnode_phandle_args args;
+
+ int ret = dev_read_phandle_with_args(dev, "altr,sysmgr-syscon", NULL,
+ 3, 0, &args);
+ if (ret) {
+ dev_err(dev, "Failed to get syscon: %d\n", ret);
+ return -EINVAL;
+ }
+
+ if (args.args_count != 3) {
+ dev_err(dev, "Invalid number of syscon args\n");
+ return -EINVAL;
+ }
+
+ reg->offset = args.args[0];
+ reg->drvsel_shift = args.args[1];
+ reg->smplsel_shift = args.args[2];
+
+ return 0;
+}
+
static void socfpga_dwmci_clksel(struct dwmci_host *host)
{
struct dwmci_socfpga_priv_data *priv = host->priv;
- u32 sdmmc_mask = ((priv->smplsel & 0x7) << SYSMGR_SDMMC_SMPLSEL_SHIFT) |
- ((priv->drvsel & 0x7) << SYSMGR_SDMMC_DRVSEL_SHIFT);
+ struct sysmgr_sdmmc_reg sdmmc_reg;
+ struct udevice *sysmgr;
+ u32 sdmmc_mask;
+
+ int ret = uclass_get_device_by_phandle(UCLASS_MISC, host->mmc->dev,
+ "altr,sysmgr-syscon", &sysmgr);
+
+ if (ret == -ENOENT) {
+ debug("%s: Could not find 'altr,sysmgr-syscon' phandle\n",
+ host->mmc->dev->name);
+ hang();
+ }
+
+ if (get_sysmgr_sdmmc_reg(host->mmc->dev, &sdmmc_reg)) {
+ debug("%s: Error reading sysmgr sdmmc reg info\n",
+ host->mmc->dev->name);
+ hang();
+ }
+
+ sdmmc_mask = ((priv->smplsel & 0x7) << sdmmc_reg.smplsel_shift) |
+ ((priv->drvsel & 0x7) << sdmmc_reg.drvsel_shift);
/* Disable SDMMC clock. */
clrbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_PERPLL_EN,
@@ -57,10 +108,12 @@ static void socfpga_dwmci_clksel(struct dwmci_host *host)
debug("%s: drvsel %d smplsel %d\n", __func__,
priv->drvsel, priv->smplsel);
- writel(sdmmc_mask, socfpga_get_sysmgr_addr() + SYSMGR_SDMMC);
+
+ misc_write(sysmgr, sdmmc_reg.offset, &sdmmc_mask, sizeof(sdmmc_mask));
+ misc_read(sysmgr, sdmmc_reg.offset, &sdmmc_mask, sizeof(sdmmc_mask));
debug("%s: SYSMGR_SDMMCGRP_CTRL_REG = 0x%x\n", __func__,
- readl(socfpga_get_sysmgr_addr() + SYSMGR_SDMMC));
+ sdmmc_mask);
/* Enable SDMMC clock */
setbits_le32(socfpga_get_clkmgr_addr() + CLKMGR_PERPLL_EN,