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