Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/marvell Add Marvell Secure Digital Input/Output (SDI...
details: https://anonhg.NetBSD.org/src/rev/0fa41f91e220
branches: trunk
changeset: 757791:0fa41f91e220
user: kiyohara <kiyohara%NetBSD.org@localhost>
date: Thu Sep 23 12:36:01 2010 +0000
description:
Add Marvell Secure Digital Input/Output (SDIO) Interface Driver.
diffstat:
sys/dev/marvell/files.discovery | 8 +-
sys/dev/marvell/mvsdio.c | 717 ++++++++++++++++++++++++++++++++++++++++
sys/dev/marvell/mvsdioreg.h | 179 +++++++++
3 files changed, 903 insertions(+), 1 deletions(-)
diffs (truncated from 923 to 300 lines):
diff -r 8669b8af5c23 -r 0fa41f91e220 sys/dev/marvell/files.discovery
--- a/sys/dev/marvell/files.discovery Thu Sep 23 12:03:27 2010 +0000
+++ b/sys/dev/marvell/files.discovery Thu Sep 23 12:36:01 2010 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files.discovery,v 1.16 2010/07/13 13:05:05 kiyohara Exp $
+# $NetBSD: files.discovery,v 1.17 2010/09/23 12:36:01 kiyohara Exp $
#
# Config file and device description for machine-independent support for
# the Marvell (formerly Galileo Technology) Discovery system controllers.
@@ -89,3 +89,9 @@
device gtidmac: dmover_service
file dev/marvell/gtidmac.c gtidmac
attach gtidmac at gt with gtidmac_gt
+
+# Secure Digital Input/Output (SDIO) Interface
+device mvsdio: sdmmcbus
+file dev/marvell/mvsdio.c mvsdio
+defparam opt_mvsdio.h MVSDIO_CARD_DETECT
+ MVSDIO_WRITE_PROTECT
diff -r 8669b8af5c23 -r 0fa41f91e220 sys/dev/marvell/mvsdio.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/dev/marvell/mvsdio.c Thu Sep 23 12:36:01 2010 +0000
@@ -0,0 +1,717 @@
+/* $NetBSD: mvsdio.c,v 1.1 2010/09/23 12:36:01 kiyohara Exp $ */
+/*
+ * Copyright (c) 2010 KIYOHARA Takashi
+ * All rights reserved.
+ *
+ * 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 AUTHOR ``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 AUTHOR 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: mvsdio.c,v 1.1 2010/09/23 12:36:01 kiyohara Exp $");
+
+#include "opt_mvsdio.h"
+
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/condvar.h>
+#include <sys/device.h>
+#include <sys/errno.h>
+#include <sys/mutex.h>
+
+#include <dev/marvell/marvellreg.h>
+#include <dev/marvell/marvellvar.h>
+#include <dev/marvell/mvsdioreg.h>
+
+#include <dev/sdmmc/sdmmcvar.h>
+#include <dev/sdmmc/sdmmcchip.h>
+
+//#define MVSDIO_DEBUG 1
+#ifdef MVSDIO_DEBUG
+#define DPRINTF(n, x) if (mvsdio_debug >= (n)) printf x
+int mvsdio_debug = MVSDIO_DEBUG;
+#else
+#define DPRINTF(n, x)
+#endif
+
+struct mvsdio_softc {
+ device_t sc_dev;
+ device_t sc_sdmmc;
+
+ bus_space_tag_t sc_iot;
+ bus_space_handle_t sc_ioh;
+ bus_dma_tag_t sc_dmat;
+
+ struct kmutex sc_mtx;
+ kcondvar_t sc_cv;
+
+ struct sdmmc_command *sc_exec_cmd;
+ uint32_t sc_waitintr;
+};
+
+static int mvsdio_match(device_t, struct cfdata *, void *);
+static void mvsdio_attach(device_t, device_t, void *);
+
+static int mvsdio_intr(void *);
+
+static int mvsdio_host_reset(sdmmc_chipset_handle_t);
+static uint32_t mvsdio_host_ocr(sdmmc_chipset_handle_t);
+static int mvsdio_host_maxblklen(sdmmc_chipset_handle_t);
+#ifdef MVSDIO_CARD_DETECT
+int MVSDIO_CARD_DETECT(sdmmc_chipset_handle_t);
+#else
+static int mvsdio_card_detect(sdmmc_chipset_handle_t);
+#endif
+#ifdef MVSDIO_WRITE_PROTECT
+int MVSDIO_WRITE_PROTECT(sdmmc_chipset_handle_t);
+#else
+static int mvsdio_write_protect(sdmmc_chipset_handle_t);
+#endif
+static int mvsdio_bus_power(sdmmc_chipset_handle_t, uint32_t);
+static int mvsdio_bus_clock(sdmmc_chipset_handle_t, int);
+static int mvsdio_bus_width(sdmmc_chipset_handle_t, int);
+static int mvsdio_bus_rod(sdmmc_chipset_handle_t, int);
+static void mvsdio_exec_command(sdmmc_chipset_handle_t, struct sdmmc_command *);
+static void mvsdio_card_enable_intr(sdmmc_chipset_handle_t, int);
+static void mvsdio_card_intr_ack(sdmmc_chipset_handle_t);
+
+static void mvsdio_wininit(struct mvsdio_softc *);
+
+static struct sdmmc_chip_functions mvsdio_chip_functions = {
+ /* host controller reset */
+ .host_reset = mvsdio_host_reset,
+
+ /* host controller capabilities */
+ .host_ocr = mvsdio_host_ocr,
+ .host_maxblklen = mvsdio_host_maxblklen,
+
+ /* card detection */
+#ifdef MVSDIO_CARD_DETECT
+ .card_detect = MVSDIO_CARD_DETECT,
+#else
+ .card_detect = mvsdio_card_detect,
+#endif
+
+ /* write protect */
+#ifdef MVSDIO_WRITE_PROTECT
+ .write_protect = MVSDIO_WRITE_PROTECT,
+#else
+ .write_protect = mvsdio_write_protect,
+#endif
+
+ /* bus power, clock frequency, width, rod */
+ .bus_power = mvsdio_bus_power,
+ .bus_clock = mvsdio_bus_clock,
+ .bus_width = mvsdio_bus_width,
+ .bus_rod = mvsdio_bus_rod,
+
+ /* command execution */
+ .exec_command = mvsdio_exec_command,
+
+ /* card interrupt */
+ .card_enable_intr = mvsdio_card_enable_intr,
+ .card_intr_ack = mvsdio_card_intr_ack,
+};
+
+CFATTACH_DECL_NEW(mvsdio_mbus, sizeof(struct mvsdio_softc),
+ mvsdio_match, mvsdio_attach, NULL, NULL);
+
+
+/* ARGSUSED */
+static int
+mvsdio_match(device_t parent, struct cfdata *match, void *aux)
+{
+ struct marvell_attach_args *mva = aux;
+
+ if (strcmp(mva->mva_name, match->cf_name) != 0)
+ return 0;
+ if (mva->mva_offset == MVA_OFFSET_DEFAULT)
+ return 0;
+
+ mva->mva_size = MVSDIO_SIZE;
+ return 1;
+}
+
+/* ARGSUSED */
+static void
+mvsdio_attach(device_t parent, device_t self, void *aux)
+{
+ struct mvsdio_softc *sc = device_private(self);
+ struct marvell_attach_args *mva = aux;
+ struct sdmmcbus_attach_args saa;
+ uint32_t nis, eis;
+
+ aprint_naive("\n");
+ aprint_normal(": Marvell Secure Digital Input/Output Interface\n");
+
+ sc->sc_dev = self;
+ sc->sc_iot = mva->mva_iot;
+ if (bus_space_subregion(mva->mva_iot, mva->mva_ioh, mva->mva_offset,
+ mva->mva_size, &sc->sc_ioh)) {
+ aprint_error_dev(self, "Cannot map registers\n");
+ return;
+ }
+ sc->sc_dmat = mva->mva_dmat;
+
+ mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_SDMMC);
+ cv_init(&sc->sc_cv, "mvsdio_intr");
+
+ sc->sc_exec_cmd = NULL;
+ sc->sc_waitintr = 0;
+
+ marvell_intr_establish(mva->mva_irq, IPL_SDMMC, mvsdio_intr, sc);
+
+ mvsdio_wininit(sc);
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HC, HC_BIGENDIAN);
+#else
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_HC, HC_LSBFIRST);
+#endif
+ nis =
+ NIS_CMDCOMPLETE /* Command Complete */ |
+ NIS_XFERCOMPLETE /* Transfer Complete */ |
+ NIS_BLOCKGAPEV /* Block gap event */ |
+ NIS_DMAINT /* DMA interrupt */ |
+ NIS_CARDINT /* Card interrupt */ |
+ NIS_READWAITON /* Read Wait state is on */ |
+ NIS_SUSPENSEON |
+ NIS_AUTOCMD12COMPLETE /* Auto_cmd12 is comp */|
+ NIS_UNEXPECTEDRESPDET |
+ NIS_ERRINT; /* Error interrupt */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NIS, nis);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NISE, nis);
+
+#define NIC_DYNAMIC_CONFIG_INTRS (NIS_CMDCOMPLETE | \
+ NIS_XFERCOMPLETE | \
+ NIS_DMAINT | \
+ NIS_CARDINT | \
+ NIS_AUTOCMD12COMPLETE)
+
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NISIE,
+ nis & ~NIC_DYNAMIC_CONFIG_INTRS);
+
+ eis =
+ EIS_CMDTIMEOUTERR /*Command timeout err*/ |
+ EIS_CMDCRCERR /* Command CRC Error */ |
+ EIS_CMDENDBITERR /*Command end bit err*/ |
+ EIS_CMDINDEXERR /*Command Index Error*/ |
+ EIS_DATATIMEOUTERR /* Data timeout error */ |
+ EIS_RDDATACRCERR /* Read data CRC err */ |
+ EIS_RDDATAENDBITERR /*Rd data end bit err*/ |
+ EIS_AUTOCMD12ERR /* Auto CMD12 error */ |
+ EIS_CMDSTARTBITERR /*Cmd start bit error*/ |
+ EIS_XFERSIZEERR /*Tx size mismatched err*/ |
+ EIS_RESPTBITERR /* Response T bit err */ |
+ EIS_CRCENDBITERR /* CRC end bit error */ |
+ EIS_CRCSTARTBITERR /* CRC start bit err */ |
+ EIS_CRCSTATERR; /* CRC status error */
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_EIS, eis);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_EISE, eis);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_EISIE, eis);
+
+ /*
+ * Attach the generic SD/MMC bus driver. (The bus driver must
+ * not invoke any chipset functions before it is attached.)
+ */
+ memset(&saa, 0, sizeof(saa));
+ saa.saa_busname = "sdmmc";
+ saa.saa_sct = &mvsdio_chip_functions;
+ saa.saa_sch = sc;
+ saa.saa_dmat = sc->sc_dmat;
+ saa.saa_clkmin = 100; /* XXXX: 100 kHz */
+ saa.saa_clkmax = MVSDIO_MAX_CLOCK;
+ saa.saa_caps = SMC_CAPS_AUTO_STOP | SMC_CAPS_4BIT_MODE | SMC_CAPS_DMA;
+#ifndef MVSDIO_CARD_DETECT
+ saa.saa_caps |= SMC_CAPS_POLL_CARD_DET;
+#endif
+ sc->sc_sdmmc = config_found(sc->sc_dev, &saa, NULL);
+}
+
+static int
+mvsdio_intr(void *arg)
+{
+ struct mvsdio_softc *sc = (struct mvsdio_softc *)arg;
+ struct sdmmc_command *cmd = sc->sc_exec_cmd;
+ uint32_t nis, eis;
+ int handled = 0, error;
+
+ nis = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NIS);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NIS, nis);
+
+ DPRINTF(3, ("%s: intr: NIS=0x%x, NISE=0x%x, NISIE=0x%x\n",
+ __func__, nis,
+ bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NISE),
+ bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_NISIE)));
+
+ if (__predict_false(nis & NIS_ERRINT)) {
+ sc->sc_exec_cmd = NULL;
+ eis = bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_EIS);
+ bus_space_write_4(sc->sc_iot, sc->sc_ioh, MVSDIO_EIS, eis);
+
+ DPRINTF(3, (" EIS=0x%x, EISE=0x%x, EISIE=0x%x\n",
+ eis,
+ bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_EISE),
+ bus_space_read_4(sc->sc_iot, sc->sc_ioh, MVSDIO_EISIE)));
+
+ if (eis & (EIS_CMDTIMEOUTERR | EIS_DATATIMEOUTERR)) {
+ error = ETIMEDOUT; /* Timeouts */
+ DPRINTF(2, (" Command/Data Timeout (0x%x)\n",
+ eis & (EIS_CMDTIMEOUTERR | EIS_DATATIMEOUTERR)));
Home |
Main Index |
Thread Index |
Old Index