[PATCH] mmc: pic32: PIC32MZDA SDHCI controller non-functional

John Robertson john.robertson at simiatec.com
Sat Aug 22 04:37:02 CEST 2020


Refresh driver code, remove obsolete DT props and set the max clock
rate from the source clock 'base_clk'.

Card detect is also broken. The fix implemented for erratum #15
documented in Microchip ref. DS80000736D only needs to be done as
in the current code (set CDSSEL, clear CDTLVL in SDHCCON1 to force
'detect') if the SDCD pin is not connected. If it is connected,
card detect works fine. A vendor specific flag 'microchip,use-sdcd'
has been added to enable real card detect functionality.

The card detect signal CDSLVL provided in the status register is
inverted as described in erratum #16, but this does not apply to
U-Boot because it uses the card inserted CARDINS flag. Therefore,
'cd-inverted' is not required.

Signed-off-by: John Robertson <john.robertson at simiatec.com>
---

 arch/mips/dts/pic32mzda_sk.dts  |  1 +
 drivers/mmc/pic32_sdhci.c       | 77 ++++++++++++++++++++-------------
 drivers/pinctrl/pinctrl_pic32.c | 28 ++++++++++++
 3 files changed, 77 insertions(+), 29 deletions(-)

diff --git a/arch/mips/dts/pic32mzda_sk.dts b/arch/mips/dts/pic32mzda_sk.dts
index b3c916a6db..fc86154e0a 100644
--- a/arch/mips/dts/pic32mzda_sk.dts
+++ b/arch/mips/dts/pic32mzda_sk.dts
@@ -40,6 +40,7 @@
 };
 
 &sdhci {
+	microchip,use-sdcd;
 	status = "okay";
 };
 
diff --git a/drivers/mmc/pic32_sdhci.c b/drivers/mmc/pic32_sdhci.c
index 029e0fbc2b..93f0532ad6 100644
--- a/drivers/mmc/pic32_sdhci.c
+++ b/drivers/mmc/pic32_sdhci.c
@@ -9,62 +9,78 @@
 #include <common.h>
 #include <dm.h>
 #include <sdhci.h>
-#include <linux/errno.h>
-#include <mach/pic32.h>
+#include <clk.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
-static int pic32_sdhci_get_cd(struct sdhci_host *host)
-{
-	/* PIC32 SDHCI CD errata:
-	 * - set CD_TEST and clear CD_TEST_INS bit
-	 */
-	sdhci_writeb(host, SDHCI_CTRL_CD_TEST, SDHCI_HOST_CONTROL);
-
-	return 0;
-}
-
-static const struct sdhci_ops pic32_sdhci_ops = {
-	.get_cd	= pic32_sdhci_get_cd,
+struct pic32_sdhci_plat {
+	struct mmc_config cfg;
+	struct mmc mmc;
 };
 
 static int pic32_sdhci_probe(struct udevice *dev)
 {
+	struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
+	struct pic32_sdhci_plat *plat = dev_get_platdata(dev);
 	struct sdhci_host *host = dev_get_priv(dev);
-	const void *fdt = gd->fdt_blob;
-	u32 f_min_max[2];
+
 	fdt_addr_t addr;
 	fdt_size_t size;
+	struct clk clk;
+	ulong clk_rate;
 	int ret;
 
-	addr = fdtdec_get_addr_size(fdt, dev_of_offset(dev), "reg", &size);
+	addr = dev_read_addr_size(dev, "reg", &size);
 	if (addr == FDT_ADDR_T_NONE)
 		return -EINVAL;
 
+	ret = clk_get_by_name(dev, "base_clk", &clk);
+	if (ret)
+		return ret;
+
+	clk_rate = clk_get_rate(&clk);
+	clk_free(&clk);
+
+	if (IS_ERR_VALUE(clk_rate))
+		return clk_rate;
+
 	host->ioaddr	= ioremap(addr, size);
 	host->name	= dev->name;
 	host->quirks	= SDHCI_QUIRK_NO_HISPD_BIT;
-	host->bus_width	= fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
-					"bus-width", 4);
-	host->ops = &pic32_sdhci_ops;
-
-	ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
-				   "clock-freq-min-max", f_min_max, 2);
-	if (ret) {
-		printf("sdhci: clock-freq-min-max not found\n");
+	host->bus_width	= dev_read_u32_default(dev, "bus-width", 4);
+	host->max_clk   = clk_rate;
+
+	host->mmc = &plat->mmc;
+	host->mmc->dev = dev;
+
+	ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
+	if (ret)
 		return ret;
-	}
 
-	host->max_clk   = f_min_max[1];
+	host->mmc->priv = host;
+	upriv->mmc = host->mmc;
 
-	ret = add_sdhci(host, 0, f_min_max[0]);
+	ret = sdhci_probe(dev);
 	if (ret)
 		return ret;
-	host->mmc->dev = dev;
+
+	if (!dev_read_bool(dev, "microchip,use-sdcd")) {
+		// Use workaround 1 for erratum #15 by default
+		u8 ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL);
+		ctrl = (ctrl & ~SDHCI_CTRL_CD_TEST_INS) | SDHCI_CTRL_CD_TEST;
+		sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL);
+	}
 
 	return 0;
 }
 
+static int pic32_sdhci_bind(struct udevice *dev)
+{
+	struct pic32_sdhci_plat *plat = dev_get_platdata(dev);
+
+	return sdhci_bind(dev, &plat->mmc, &plat->cfg);
+}
+
 static const struct udevice_id pic32_sdhci_ids[] = {
 	{ .compatible = "microchip,pic32mzda-sdhci" },
 	{ }
@@ -74,6 +90,9 @@ U_BOOT_DRIVER(pic32_sdhci_drv) = {
 	.name			= "pic32_sdhci",
 	.id			= UCLASS_MMC,
 	.of_match		= pic32_sdhci_ids,
+	.ops			= &sdhci_ops,
+	.bind			= pic32_sdhci_bind,
 	.probe			= pic32_sdhci_probe,
 	.priv_auto_alloc_size	= sizeof(struct sdhci_host),
+	.platdata_auto_alloc_size = sizeof(struct pic32_sdhci_plat)
 };
diff --git a/drivers/pinctrl/pinctrl_pic32.c b/drivers/pinctrl/pinctrl_pic32.c
index 911af1297b..899c279975 100644
--- a/drivers/pinctrl/pinctrl_pic32.c
+++ b/drivers/pinctrl/pinctrl_pic32.c
@@ -222,6 +222,31 @@ static void pic32_eth_pin_config(struct udevice *dev)
 	pic32_pinconfig_set(priv, configs, ARRAY_SIZE(configs));
 }
 
+static void pic32_sdhci_pin_config(struct udevice *dev)
+{
+	struct pic32_pinctrl_priv *priv = dev_get_priv(dev);
+	const struct pic32_pin_config configs[] = {
+		/* SDWP - H2 */
+		PIN_CONFIG(PIC32_PORT_H, 2, PIN_CONFIG_PIC32_DIGITAL),
+		/* SDCD - A0 */
+		PIN_CONFIG(PIC32_PORT_A, 0, PIN_CONFIG_PIC32_DIGITAL),
+		/* SDCMD - D4 */
+		PIN_CONFIG(PIC32_PORT_D, 4, PIN_CONFIG_PIC32_DIGITAL),
+		/* SDCK - A6 */
+		PIN_CONFIG(PIC32_PORT_A, 6, PIN_CONFIG_PIC32_DIGITAL),
+		/* SDDATA0 - G13 */
+		PIN_CONFIG(PIC32_PORT_G, 13, PIN_CONFIG_PIC32_DIGITAL),
+		/* SDDATA1 - G12 */
+		PIN_CONFIG(PIC32_PORT_G, 12, PIN_CONFIG_PIC32_DIGITAL),
+		/* SDDATA2 - G14 */
+		PIN_CONFIG(PIC32_PORT_G, 14, PIN_CONFIG_PIC32_DIGITAL),
+		/* SDDATA3 - A7 */
+		PIN_CONFIG(PIC32_PORT_A, 7, PIN_CONFIG_PIC32_DIGITAL),
+	};
+
+	pic32_pinconfig_set(priv, configs, ARRAY_SIZE(configs));
+}
+
 static int pic32_pinctrl_request(struct udevice *dev, int func, int flags)
 {
 	struct pic32_pinctrl_priv *priv = dev_get_priv(dev);
@@ -240,6 +265,9 @@ static int pic32_pinctrl_request(struct udevice *dev, int func, int flags)
 	case PERIPH_ID_ETH:
 		pic32_eth_pin_config(dev);
 		break;
+	case PERIPH_ID_SDHCI:
+		pic32_sdhci_pin_config(dev);
+		break;
 	default:
 		debug("%s: unknown-unhandled case\n", __func__);
 		break;
-- 
2.28.0



More information about the U-Boot mailing list