[U-Boot] [PATCH] ARM: aspeed: Add SD host controller driver

Eddie James eajames at linux.ibm.com
Mon Aug 12 20:53:36 UTC 2019


Add support for the Aspeed SD host controller engine. This involves
adding an MMC SDHCI driver and various additions to the clock and reset
drivers for Aspeed chips.

Signed-off-by: Eddie James <eajames at linux.ibm.com>
---
 arch/arm/include/asm/arch-aspeed/scu_ast2500.h |  3 +
 arch/arm/include/asm/gpio.h                    |  3 +-
 arch/arm/mach-aspeed/ast2500-board.c           |  3 +
 drivers/clk/aspeed/clk_ast2500.c               | 27 +++++++++
 drivers/mmc/Kconfig                            | 11 ++++
 drivers/mmc/Makefile                           |  1 +
 drivers/mmc/aspeed_sdhci.c                     | 78 ++++++++++++++++++++++++++
 drivers/pinctrl/aspeed/pinctrl_ast2500.c       |  2 +
 8 files changed, 127 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mmc/aspeed_sdhci.c

diff --git a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
index 4988ced..8db4901 100644
--- a/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
+++ b/arch/arm/include/asm/arch-aspeed/scu_ast2500.h
@@ -22,6 +22,8 @@
 #define SCU_MPLL_POST_MASK		(0x3f << SCU_MPLL_POST_SHIFT)
 #define SCU_PCLK_DIV_SHIFT		23
 #define SCU_PCLK_DIV_MASK		(7 << SCU_PCLK_DIV_SHIFT)
+#define SCU_SDCLK_DIV_SHIFT		12
+#define SCU_SDCLK_DIV_MASK		(7 << SCU_SDCLK_DIV_SHIFT)
 #define SCU_HPLL_DENUM_SHIFT		0
 #define SCU_HPLL_DENUM_MASK		0x1f
 #define SCU_HPLL_NUM_SHIFT		5
@@ -107,6 +109,7 @@
 
 #define SCU_CLKSTOP_MAC1		(1 << 20)
 #define SCU_CLKSTOP_MAC2		(1 << 21)
+#define SCU_CLKSTOP_SDCLK		(1 << 27)
 
 #define SCU_D2PLL_EXT1_OFF		(1 << 0)
 #define SCU_D2PLL_EXT1_BYPASS		(1 << 1)
diff --git a/arch/arm/include/asm/gpio.h b/arch/arm/include/asm/gpio.h
index 370031f..38a5922 100644
--- a/arch/arm/include/asm/gpio.h
+++ b/arch/arm/include/asm/gpio.h
@@ -1,6 +1,7 @@
 #if !defined(CONFIG_ARCH_UNIPHIER) && !defined(CONFIG_ARCH_STI) && \
 	!defined(CONFIG_ARCH_K3) && !defined(CONFIG_ARCH_BCM6858) && \
-	!defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP)
+	!defined(CONFIG_ARCH_BCM63158) && !defined(CONFIG_ARCH_ROCKCHIP) && \
+	!defined(CONFIG_ARCH_ASPEED)
 #include <asm/arch/gpio.h>
 #endif
 #include <asm-generic/gpio.h>
diff --git a/arch/arm/mach-aspeed/ast2500-board.c b/arch/arm/mach-aspeed/ast2500-board.c
index e7edd54..52a4e05 100644
--- a/arch/arm/mach-aspeed/ast2500-board.c
+++ b/arch/arm/mach-aspeed/ast2500-board.c
@@ -4,6 +4,7 @@
  */
 #include <common.h>
 #include <dm.h>
+#include <mmc.h>
 #include <ram.h>
 #include <timer.h>
 #include <asm/io.h>
@@ -55,6 +56,8 @@ int board_init(void)
 {
 	gd->bd->bi_boot_params = CONFIG_SYS_SDRAM_BASE + 0x100;
 
+	mmc_initialize(gd->bd);
+
 	return 0;
 }
 
diff --git a/drivers/clk/aspeed/clk_ast2500.c b/drivers/clk/aspeed/clk_ast2500.c
index dbee13a..9249cf9 100644
--- a/drivers/clk/aspeed/clk_ast2500.c
+++ b/drivers/clk/aspeed/clk_ast2500.c
@@ -143,6 +143,17 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
 			rate = rate / apb_div;
 		}
 		break;
+	case BCLK_SDCLK:
+		{
+			ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
+						  & SCU_SDCLK_DIV_MASK)
+						 >> SCU_SDCLK_DIV_SHIFT);
+			rate = ast2500_get_hpll_rate(clkin,
+						     readl(&priv->
+							   scu->h_pll_param));
+			rate = rate / apb_div;
+		}
+		break;
 	case PCLK_UART1:
 		rate = ast2500_get_uart_clk_rate(priv->scu, 1);
 		break;
@@ -436,6 +447,22 @@ static int ast2500_clk_enable(struct clk *clk)
 	struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
 
 	switch (clk->id) {
+	case BCLK_SDCLK:
+		if (readl(&priv->scu->clk_stop_ctrl1) & SCU_CLKSTOP_SDCLK) {
+			ast_scu_unlock(priv->scu);
+
+			setbits_le32(&priv->scu->sysreset_ctrl1,
+				     SCU_SYSRESET_SDIO);
+			udelay(100);
+			clrbits_le32(&priv->scu->clk_stop_ctrl1,
+				     SCU_CLKSTOP_SDCLK);
+			mdelay(10);
+			clrbits_le32(&priv->scu->sysreset_ctrl1,
+				     SCU_SYSRESET_SDIO);
+
+			ast_scu_lock(priv->scu);
+		}
+		break;
 	/*
 	 * For MAC clocks the clock rate is
 	 * configured based on whether RGMII or RMII mode has been selected
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index c6812f6..536f66a 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -421,6 +421,17 @@ config SPL_MMC_SDHCI_ADMA
 	  This enables support for the ADMA (Advanced DMA) defined
 	  in the SD Host Controller Standard Specification Version 3.00 in SPL.
 
+config MMC_SDHCI_ASPEED
+	bool "Aspeed SDHCI controller"
+	depends on ARCH_ASPEED
+	depends on DM_MMC
+	depends on MMC_SDHCI
+	help
+	  Enables support for the Aspeed SDHCI 2.0 controller present on Aspeed
+	  SoCs. This device is compatible with SD 3.0 and/or MMC 4.3
+	  specifications. On the AST2600, the device is also compatible with
+	  MMC 5.1 and eMMC 3.0.
+
 config MMC_SDHCI_ATMEL
 	bool "Atmel SDHCI controller support"
 	depends on ARCH_AT91
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 6cc018b..5594195 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_JZ47XX_MMC) += jz_mmc.o
 
 # SDHCI
 obj-$(CONFIG_MMC_SDHCI)			+= sdhci.o
+obj-$(CONFIG_MMC_SDHCI_ASPEED)		+= aspeed_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_ATMEL)		+= atmel_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_BCM2835)		+= bcm2835_sdhci.o
 obj-$(CONFIG_MMC_SDHCI_BCMSTB)		+= bcmstb_sdhci.o
diff --git a/drivers/mmc/aspeed_sdhci.c b/drivers/mmc/aspeed_sdhci.c
new file mode 100644
index 0000000..c292c42
--- /dev/null
+++ b/drivers/mmc/aspeed_sdhci.c
@@ -0,0 +1,78 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright 2019 IBM Corp.
+ * Eddie James <eajames at linux.ibm.com>
+ */
+
+#include <common.h>
+#include <clk.h>
+#include <dm.h>
+#include <malloc.h>
+#include <sdhci.h>
+
+struct aspeed_sdhci_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
+};
+
+static int aspeed_sdhci_probe(struct udevice *dev)
+{
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct aspeed_sdhci_plat *plat = dev_get_platdata(dev);
+	struct sdhci_host *host = dev_get_priv(dev);
+	u32 max_clk;
+	struct clk clk;
+	int ret;
+
+	ret = clk_get_by_index(dev, 0, &clk);
+	if (ret)
+		return ret;
+
+	ret = clk_enable(&clk);
+	if (ret)
+		return ret;
+
+	host->name = dev->name;
+	host->ioaddr = (void *)devfdt_get_addr(dev);
+
+	max_clk = clk_get_rate(&clk);
+	if (!max_clk)
+		return -EINVAL;
+
+	host->max_clk = max_clk;
+	host->mmc = &plat->mmc;
+	host->mmc->dev = dev;
+	host->mmc->priv = host;
+	upriv->mmc = host->mmc;
+
+	ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
+	if (ret)
+		return ret;
+
+	return sdhci_probe(dev);
+}
+
+static int aspeed_sdhci_bind(struct udevice *dev)
+{
+	struct aspeed_sdhci_plat *plat = dev_get_platdata(dev);
+
+	return sdhci_bind(dev, &plat->mmc, &plat->cfg);
+}
+
+static const struct udevice_id aspeed_sdhci_ids[] = {
+	{ .compatible = "aspeed,ast2400-sdhci" },
+	{ .compatible = "aspeed,ast2500-sdhci" },
+	{ .compatible = "aspeed,ast2600-sdhci" },
+	{ }
+};
+
+U_BOOT_DRIVER(aspeed_sdhci_drv) = {
+	.name		= "aspeed_sdhci",
+	.id		= UCLASS_MMC,
+	.of_match	= aspeed_sdhci_ids,
+	.ops		= &sdhci_ops,
+	.bind		= aspeed_sdhci_bind,
+	.probe		= aspeed_sdhci_probe,
+	.priv_auto_alloc_size = sizeof(struct sdhci_host),
+	.platdata_auto_alloc_size = sizeof(struct aspeed_sdhci_plat),
+};
diff --git a/drivers/pinctrl/aspeed/pinctrl_ast2500.c b/drivers/pinctrl/aspeed/pinctrl_ast2500.c
index ed333b9..a6e9c0d 100644
--- a/drivers/pinctrl/aspeed/pinctrl_ast2500.c
+++ b/drivers/pinctrl/aspeed/pinctrl_ast2500.c
@@ -58,6 +58,8 @@ static const struct ast2500_group_config ast2500_groups[] = {
 	{ "MDIO1", 3, (1 << 31) | (1 << 30) },
 	{ "MAC2LINK", 1, (1 << 1) },
 	{ "MDIO2", 5, (1 << 2) },
+	{ "SD1", 5, (1 << 0) },
+	{ "SD2", 5, (1 << 1) },
 };
 
 static int ast2500_pinctrl_get_groups_count(struct udevice *dev)
-- 
1.8.3.1



More information about the U-Boot mailing list