[U-Boot] [PATCH v1 15/18] drivers: mmc: add driver for Microchip PIC32, SDHCI controller.

Purna Chandra Mandal purna.mandal at microchip.com
Thu Dec 17 18:33:48 CET 2015


From: Andrei Pistirica <andrei.pistirica at microchip.com>

This driver implements platform specific glue and fix-ups for SDHCI host controller.

Signed-off-by: Andrei Pistirica <andrei.pistirica at microchip.com>
Signed-off-by: Purna Chandra Mandal <purna.mandal at microchip.com>
---

 drivers/mmc/Kconfig       |   6 +++
 drivers/mmc/Makefile      |   2 +-
 drivers/mmc/pic32_sdhci.c | 110 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 117 insertions(+), 1 deletion(-)
 create mode 100644 drivers/mmc/pic32_sdhci.c

diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig
index ceae7bc..0b6f54b 100644
--- a/drivers/mmc/Kconfig
+++ b/drivers/mmc/Kconfig
@@ -31,4 +31,10 @@ config SH_SDHI
     help
       Support for the on-chip SDHI host controller on SuperH/Renesas ARM SoCs platform
 
+config PIC32_SDHCI
+    bool "Microchip PIC32 on-chip SDHCI support"
+    depends on DM_MMC && MACH_PIC32
+    help
+      Support for the on-chip SDHCI support on Microchip PIC32 platforms.
+
 endmenu
diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile
index 5d35705..c9c3e3e 100644
--- a/drivers/mmc/Makefile
+++ b/drivers/mmc/Makefile
@@ -48,4 +48,4 @@ obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o
 else
 obj-$(CONFIG_GENERIC_MMC) += mmc_write.o
 endif
-
+obj-$(CONFIG_PIC32_SDHCI) += pic32_sdhci.o
diff --git a/drivers/mmc/pic32_sdhci.c b/drivers/mmc/pic32_sdhci.c
new file mode 100644
index 0000000..4fe0825
--- /dev/null
+++ b/drivers/mmc/pic32_sdhci.c
@@ -0,0 +1,110 @@
+/*
+ * Support of SDHCI devices for Microchip PIC32 SoC.
+ *
+ * Copyright (C) 2015 Microchip Technology Inc.
+ * Andrei Pistirica <andrei.pistirica at microchip.com>
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <malloc.h>
+#include <sdhci.h>
+#include <asm/errno.h>
+#include <asm/arch-pic32/pic32.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* SDHCI capabilities bits */
+#define SDHCI_CAPS_SLOT_TYPE_MASK        0xC0000000
+#define  SLOT_TYPE_REMOVABLE            0x0
+#define  SLOT_TYPE_EMBEDDED            0x1
+#define  SLOT_TYPE_SHARED_BUS            0x2
+
+/* SDHCI Shared Bus Control */
+#define SDHCI_SHARED_BUS_CTRL            0xE0
+#define  SDHCI_SHARED_BUS_NR_CLK_PINS_MASK    0x7
+#define  SDHCI_SHARED_BUS_NR_IRQ_PINS_MASK    0x30
+#define  SDHCI_SHARED_BUS_CLK_PINS        0x10
+#define  SDHCI_SHARED_BUS_IRQ_PINS        0x14
+
+static int pic32_sdhci_set_shared(struct sdhci_host *host, u32 clk, u32 irq)
+{
+    unsigned int caps;
+    u32 bus, caps_slot_type;
+    u32 clk_pins, irq_pins;
+
+    /* Card slot connected on shared bus? */
+    caps = sdhci_readl(host, SDHCI_CAPABILITIES);
+    caps_slot_type = ((caps & SDHCI_CAPS_SLOT_TYPE_MASK) >> 30);
+    if (caps_slot_type != SLOT_TYPE_SHARED_BUS)
+        return 0;
+
+    bus = sdhci_readl(host, SDHCI_SHARED_BUS_CTRL);
+    clk_pins = (bus & SDHCI_SHARED_BUS_NR_CLK_PINS_MASK) >> 0;
+    irq_pins = (bus & SDHCI_SHARED_BUS_NR_IRQ_PINS_MASK) >> 4;
+
+    /* Select first clock */
+    if (clk_pins & clk)
+        bus |= (clk << SDHCI_SHARED_BUS_CLK_PINS);
+
+    /* Select first interrupt */
+    if (irq_pins & irq)
+        bus |= (irq << SDHCI_SHARED_BUS_IRQ_PINS);
+
+    sdhci_writel(host, bus, SDHCI_SHARED_BUS_CTRL);
+    return 0;
+}
+
+static int pic32_sdhci_probe(struct udevice *dev)
+{
+    struct sdhci_host *host = dev_get_priv(dev);
+    u32 minmax[2], shared_clk_irq[2];
+    int ret;
+
+    ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
+                   "clock-freq-min-max", minmax, 2);
+    if (ret)
+        goto _out;
+
+    ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset,
+                   "clock-irq-pins", shared_clk_irq, 2);
+    if (!ret)
+        ret = pic32_sdhci_set_shared(host, shared_clk_irq[1],
+                         shared_clk_irq[0]);
+
+    if (ret)
+        goto _out;
+
+    return add_sdhci(host, minmax[1], minmax[0]);
+
+_out:
+    return ret;
+}
+
+
+static int pic32_sdhci_ofdata_to_platdata(struct udevice *dev)
+{
+    struct sdhci_host *host = dev_get_priv(dev);
+
+    host->name    = (char *)dev->name;
+    host->ioaddr    = (void *)dev_get_addr(dev);
+    host->quirks    = SDHCI_QUIRK_NO_HISPD_BIT;
+    host->bus_width    = fdtdec_get_int(gd->fdt_blob, dev->of_offset,
+                    "bus-width", 4);
+    return 0;
+}
+static const struct udevice_id pic32_sdhci_ids[] = {
+    { .compatible = "microchip,pic32mzda-sdhci" },
+    { }
+};
+
+U_BOOT_DRIVER(pic32_sdhci_drv) = {
+    .name            = "pic32_sdhci",
+    .id            = UCLASS_MMC,
+    .of_match        = pic32_sdhci_ids,
+    .probe            = pic32_sdhci_probe,
+    .ofdata_to_platdata    = pic32_sdhci_ofdata_to_platdata,
+    .priv_auto_alloc_size    = sizeof(struct sdhci_host),
+};
-- 
1.8.3.1



More information about the U-Boot mailing list