Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/ti Add MMCHS support.



details:   https://anonhg.NetBSD.org/src/rev/937ab0142490
branches:  trunk
changeset: 460534:937ab0142490
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun Oct 27 15:43:46 2019 +0000

description:
Add MMCHS support.

diffstat:

 sys/arch/arm/ti/files.ti     |    6 +-
 sys/arch/arm/ti/ti_sdhc.c    |  672 +++++++++++++++++++++++++++++++++++++++++++
 sys/arch/arm/ti/ti_sdhcreg.h |   98 ++++++
 3 files changed, 775 insertions(+), 1 deletions(-)

diffs (truncated from 798 to 300 lines):

diff -r f78c05c79951 -r 937ab0142490 sys/arch/arm/ti/files.ti
--- a/sys/arch/arm/ti/files.ti  Sun Oct 27 15:31:15 2019 +0000
+++ b/sys/arch/arm/ti/files.ti  Sun Oct 27 15:43:46 2019 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.ti,v 1.8 2019/10/27 12:14:51 jmcneill Exp $
+#      $NetBSD: files.ti,v 1.9 2019/10/27 15:43:46 jmcneill Exp $
 #
 
 file   arch/arm/ti/ti_platform.c       soc_ti
@@ -44,6 +44,10 @@
 attach titptc at fdt with ti_tptc
 file   arch/arm/ti/ti_tptc.c           ti_tptc
 
+# MMCHS
+attach sdhc at fdt with ti_sdhc: ti_edma, ti_prcm
+file   arch/arm/ti/ti_sdhc.c           ti_sdhc
+
 # SOC parameters
 defflag        opt_soc.h                       SOC_TI
 defflag        opt_soc.h                       SOC_TI_AM335X: SOC_TI
diff -r f78c05c79951 -r 937ab0142490 sys/arch/arm/ti/ti_sdhc.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/arch/arm/ti/ti_sdhc.c Sun Oct 27 15:43:46 2019 +0000
@@ -0,0 +1,672 @@
+/*     $NetBSD: ti_sdhc.c,v 1.1 2019/10/27 15:43:46 jmcneill Exp $     */
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas of 3am Software Foundry.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: ti_sdhc.c,v 1.1 2019/10/27 15:43:46 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/errno.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/bus.h>
+
+#include <arm/ti/ti_prcm.h>
+#include <arm/ti/ti_edma.h>
+#include <arm/ti/ti_sdhcreg.h>
+
+#include <dev/sdmmc/sdhcreg.h>
+#include <dev/sdmmc/sdhcvar.h>
+#include <dev/sdmmc/sdmmcvar.h>
+
+#include <dev/fdt/fdtvar.h>
+
+#define EDMA_MAX_PARAMS                32
+
+#ifdef TISDHC_DEBUG
+int tisdhcdebug = 1;
+#define DPRINTF(n,s)    do { if ((n) <= tisdhcdebug) device_printf s; } while (0)
+#else
+#define DPRINTF(n,s)    do {} while (0)
+#endif
+
+
+#define CLKD(kz)       (sc->sc.sc_clkbase / (kz))
+
+#define SDHC_READ(sc, reg) \
+       bus_space_read_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg))
+#define SDHC_WRITE(sc, reg, val) \
+       bus_space_write_4((sc)->sc_bst, (sc)->sc_sdhc_bsh, (reg), (val))
+
+struct ti_sdhc_config {
+       bus_size_t              regoff;
+       uint32_t                flags;
+};
+
+static const struct ti_sdhc_config omap2_hsmmc_config = {
+};
+
+static const struct ti_sdhc_config omap3_pre_es3_hsmmc_config = {
+       .flags = SDHC_FLAG_SINGLE_ONLY
+};
+
+static const struct ti_sdhc_config omap4_hsmmc_config = {
+       .regoff = 0x100
+};
+
+static const struct of_compat_data compat_data[] = {
+       { "ti,omap2-hsmmc",             (uintptr_t)&omap2_hsmmc_config },
+       { "ti,omap3-hsmmc",             (uintptr_t)&omap2_hsmmc_config },
+       { "ti,omap3-pre-es3-hsmmc",     (uintptr_t)&omap3_pre_es3_hsmmc_config },
+       { "ti,omap4-hsmmc",             (uintptr_t)&omap4_hsmmc_config },
+       { NULL }
+};
+
+enum {
+       EDMA_CHAN_TX,
+       EDMA_CHAN_RX,
+       EDMA_NCHAN
+};
+
+struct ti_sdhc_softc {
+       struct sdhc_softc       sc;
+       int                     sc_phandle;
+       bus_addr_t              sc_addr;
+       bus_space_tag_t         sc_bst;
+       bus_space_handle_t      sc_bsh;
+       bus_space_handle_t      sc_hl_bsh;
+       bus_space_handle_t      sc_sdhc_bsh;
+       struct sdhc_host        *sc_hosts[1];
+       void                    *sc_ih;         /* interrupt vectoring */
+
+       int                     sc_edma_chan[EDMA_NCHAN];
+       struct edma_channel     *sc_edma_tx;
+       struct edma_channel     *sc_edma_rx;
+       uint16_t                sc_edma_param_tx[EDMA_MAX_PARAMS];
+       uint16_t                sc_edma_param_rx[EDMA_MAX_PARAMS];
+       kcondvar_t              sc_edma_cv;
+       bus_addr_t              sc_edma_fifo;
+       bool                    sc_edma_pending;
+       bus_dmamap_t            sc_edma_dmamap;
+       bus_dma_segment_t       sc_edma_segs[1];
+       void                    *sc_edma_bbuf;
+};
+
+static int ti_sdhc_match(device_t, cfdata_t, void *);
+static void ti_sdhc_attach(device_t, device_t, void *);
+
+static void ti_sdhc_init(struct ti_sdhc_softc *, const struct ti_sdhc_config *);
+
+static int ti_sdhc_bus_width(struct sdhc_softc *, int);
+static int ti_sdhc_rod(struct sdhc_softc *, int);
+static int ti_sdhc_write_protect(struct sdhc_softc *);
+static int ti_sdhc_card_detect(struct sdhc_softc *);
+
+static int ti_sdhc_edma_init(struct ti_sdhc_softc *, u_int, u_int);
+static int ti_sdhc_edma_xfer_data(struct sdhc_softc *, struct sdmmc_command *);
+static void ti_sdhc_edma_done(void *);
+static int ti_sdhc_edma_transfer(struct sdhc_softc *, struct sdmmc_command *);
+
+CFATTACH_DECL_NEW(ti_sdhc, sizeof(struct ti_sdhc_softc),
+    ti_sdhc_match, ti_sdhc_attach, NULL, NULL);
+
+static int
+ti_sdhc_match(device_t parent, cfdata_t cf, void *aux)
+{
+       struct fdt_attach_args * const faa = aux;
+
+       return of_match_compat_data(faa->faa_phandle, compat_data);
+}
+
+static void
+ti_sdhc_attach(device_t parent, device_t self, void *aux)
+{
+       struct ti_sdhc_softc * const sc = device_private(self);
+       struct fdt_attach_args * const faa = aux;
+       const int phandle = faa->faa_phandle;
+       const struct ti_sdhc_config *conf;
+       bus_addr_t addr;
+       bus_size_t size;
+       u_int bus_width;
+
+       conf = (const void *)of_search_compatible(phandle, compat_data)->data;
+
+       if (ti_prcm_enable_hwmod(OF_parent(phandle), 0) != 0) {
+               aprint_error(": couldn't enable module\n");
+               return;
+       }
+
+       if (fdtbus_get_reg(phandle, 0, &addr, &size) != 0 || size <= conf->regoff) {
+               aprint_error(": couldn't get registers\n");
+               return;
+       }
+       addr += conf->regoff;
+       size -= conf->regoff;
+
+       sc->sc.sc_dmat = faa->faa_dmat;
+       sc->sc.sc_dev = self;
+       sc->sc_phandle = phandle;
+       sc->sc_addr = addr;
+       sc->sc_bst = faa->faa_bst;
+
+#if notyet
+       /* XXX use fdtbus_dma API */
+       int len;
+       const u_int *dmas = fdtbus_get_prop(phandle, "dmas", &len);
+       switch (len) {
+       case 24:
+               sc->sc_edma_chan[EDMA_CHAN_TX] = be32toh(dmas[1]);
+               sc->sc_edma_chan[EDMA_CHAN_RX] = be32toh(dmas[4]);
+               break;
+       case 32:
+               sc->sc_edma_chan[EDMA_CHAN_TX] = be32toh(dmas[1]);
+               sc->sc_edma_chan[EDMA_CHAN_RX] = be32toh(dmas[5]);
+               break;
+       default:
+               sc->sc_edma_chan[EDMA_CHAN_TX] = -1;
+               sc->sc_edma_chan[EDMA_CHAN_RX] = -1;
+               break;
+       }
+#else
+       sc->sc_edma_chan[EDMA_CHAN_TX] = -1;
+       sc->sc_edma_chan[EDMA_CHAN_RX] = -1;
+#endif
+
+       if (bus_space_map(sc->sc_bst, addr, size, 0, &sc->sc_bsh) != 0) {
+               aprint_error(": couldn't map registers\n");
+               return;
+       }
+
+       if (of_getprop_uint32(phandle, "bus-width", &bus_width) != 0)
+               bus_width = 4;
+
+       sc->sc.sc_flags |= conf->flags;
+       sc->sc.sc_flags |= SDHC_FLAG_32BIT_ACCESS;
+       sc->sc.sc_flags |= SDHC_FLAG_NO_LED_ON;
+       sc->sc.sc_flags |= SDHC_FLAG_RSP136_CRC;
+       if (bus_width == 8)
+               sc->sc.sc_flags |= SDHC_FLAG_8BIT_MODE;
+       if (of_hasprop(phandle, "ti,needs-special-reset"))
+               sc->sc.sc_flags |= SDHC_FLAG_WAIT_RESET;
+       if (of_hasprop(phandle, "ti,needs-special-hs-handling"))
+               sc->sc.sc_flags |= SDHC_FLAG_NO_HS_BIT;
+       if (of_hasprop(phandle, "ti,dual-volt"))
+               sc->sc.sc_caps = SDHC_VOLTAGE_SUPP_3_0V;
+
+       sc->sc.sc_host = sc->sc_hosts;
+       sc->sc.sc_clkbase = 96000;      /* 96MHZ */
+       sc->sc.sc_clkmsk = 0x0000ffc0;
+       sc->sc.sc_vendor_rod = ti_sdhc_rod;
+       sc->sc.sc_vendor_write_protect = ti_sdhc_write_protect;
+       sc->sc.sc_vendor_card_detect = ti_sdhc_card_detect;
+       sc->sc.sc_vendor_bus_width = ti_sdhc_bus_width;
+
+       if (bus_space_subregion(sc->sc_bst, sc->sc_bsh, 0x100, 0x100,
+           &sc->sc_sdhc_bsh) != 0) {
+               aprint_error(": couldn't map subregion\n");
+               return;
+       }
+
+       aprint_naive("\n");
+       aprint_normal(": MMCHS\n");
+
+       ti_sdhc_init(sc, conf);
+}
+
+static void
+ti_sdhc_init(struct ti_sdhc_softc *sc, const struct ti_sdhc_config *conf)
+{
+       device_t dev = sc->sc.sc_dev;
+       uint32_t clkd, stat;
+       int error, timo, clksft, n;
+       char intrstr[128];
+
+       const int tx_chan = sc->sc_edma_chan[EDMA_CHAN_TX];
+       const int rx_chan = sc->sc_edma_chan[EDMA_CHAN_RX];
+
+       if (tx_chan != -1 && rx_chan != -1) {
+               aprint_normal_dev(dev,
+                   "EDMA tx channel %d, rx channel %d\n",
+                   tx_chan, rx_chan);
+
+               if (ti_sdhc_edma_init(sc, tx_chan, rx_chan) != 0) {
+                       aprint_error_dev(dev, "EDMA disabled\n");
+                       goto no_dma;
+               }
+
+               cv_init(&sc->sc_edma_cv, "sdhcedma");
+               sc->sc_edma_fifo = sc->sc_addr + 0x100 + SDHC_DATA;
+               sc->sc.sc_flags |= SDHC_FLAG_USE_DMA;
+               sc->sc.sc_flags |= SDHC_FLAG_EXTERNAL_DMA;
+               sc->sc.sc_flags |= SDHC_FLAG_EXTDMA_DMAEN;
+               sc->sc.sc_vendor_transfer_data_dma = ti_sdhc_edma_xfer_data;
+       }
+no_dma:
+



Home | Main Index | Thread Index | Old Index