Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 Apr 2012 00:43:32 +0000 (UTC)
From:      Marius Strobl <marius@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r234560 - head/sys/arm/at91
Message-ID:  <201204220043.q3M0hWT7011795@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marius
Date: Sun Apr 22 00:43:32 2012
New Revision: 234560
URL: http://svn.freebsd.org/changeset/base/234560

Log:
  - Add support for MCI1 revision 2xx controllers and a work-around for their
    "Data Write Operation and number of bytes" erratum.
  - Use DEVMETHOD_END.
  - Use NULL instead of 0 for pointers.

Modified:
  head/sys/arm/at91/at91_mci.c
  head/sys/arm/at91/at91_mcireg.h

Modified: head/sys/arm/at91/at91_mci.c
==============================================================================
--- head/sys/arm/at91/at91_mci.c	Sat Apr 21 20:22:02 2012	(r234559)
+++ head/sys/arm/at91/at91_mci.c	Sun Apr 22 00:43:32 2012	(r234560)
@@ -113,6 +113,7 @@ static void at91_mci_intr(void *);
 /* helper routines */
 static int at91_mci_activate(device_t dev);
 static void at91_mci_deactivate(device_t dev);
+static int at91_mci_is_mci1rev2xx(void);
 
 #define AT91_MCI_LOCK(_sc)		mtx_lock(&(_sc)->sc_mtx)
 #define	AT91_MCI_UNLOCK(_sc)		mtx_unlock(&(_sc)->sc_mtx)
@@ -141,11 +142,16 @@ static void
 at91_mci_init(device_t dev)
 {
 	struct at91_mci_softc *sc = device_get_softc(dev);
+	uint32_t val;
 
 	WR4(sc, MCI_CR, MCI_CR_MCIEN);		/* Enable controller */
 	WR4(sc, MCI_IDR, 0xffffffff);		/* Turn off interrupts */
 	WR4(sc, MCI_DTOR, MCI_DTOR_DTOMUL_1M | 1);
-	WR4(sc, MCI_MR, 0x834a);	// XXX GROSS HACK FROM LINUX
+	val = MCI_MR_PDCMODE;
+	val |= 0x34a;				/* PWSDIV = 3; CLKDIV = 74 */
+	if (at91_mci_is_mci1rev2xx())
+		val |= MCI_MR_RDPROOF | MCI_MR_WRPROOF;
+	WR4(sc, MCI_MR, val);
 #ifndef  AT91_MCI_SLOT_B
 	WR4(sc, MCI_SDCR, 0);			/* SLOT A, 1 bit bus */
 #else
@@ -303,6 +309,29 @@ at91_mci_deactivate(device_t dev)
 	return;
 }
 
+static int
+at91_mci_is_mci1rev2xx(void)
+{
+
+	switch (AT91_CPU(at91_chip_id)) {
+	case AT91_CPU_SAM9260:
+	case AT91_CPU_SAM9263:
+#ifdef notyet
+	case AT91_CPU_CAP9:
+#endif
+	case AT91_CPU_SAM9G10:
+	case AT91_CPU_SAM9G20:
+#ifdef notyet
+	case AT91_CPU_SAM9RL:
+#endif
+	case AT91_CPU_SAM9XE128:
+	case AT91_CPU_SAM9XE256:
+	case AT91_CPU_SAM9XE512:
+		return(1);
+	}
+	return (0);
+}
+
 static void
 at91_mci_getaddr(void *arg, bus_dma_segment_t *segs, int nsegs, int error)
 {
@@ -346,6 +375,7 @@ at91_mci_update_ios(device_t brdev, devi
 static void
 at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd)
 {
+	size_t len;
 	uint32_t cmdr, ier = 0, mr;
 	uint32_t *src, *dst;
 	int i;
@@ -397,6 +427,7 @@ at91_mci_start_cmd(struct at91_mci_softc
 	WR4(sc, MCI_MR, mr | (data->len << 16) | MCI_MR_PDCMODE);
 	WR4(sc, PDC_PTCR, PDC_PTCR_RXTDIS | PDC_PTCR_TXTDIS);
 	if (cmdr & MCI_CMDR_TRCMD_START) {
+		len = data->len;
 		if (cmdr & MCI_CMDR_TRDIR)
 			vaddr = cmd->data->data;
 		else {
@@ -411,6 +442,15 @@ at91_mci_start_cmd(struct at91_mci_softc
 			vaddr = sc->bounce_buffer;
 			src = (uint32_t *)cmd->data->data;
 			dst = (uint32_t *)vaddr;
+			/*
+			 * If this is MCI1 revision 2xx controller, apply
+			 * a work-around for the "Data Write Operation and
+			 * number of bytes" erratum.
+			 */
+			if (at91_mci_is_mci1rev2xx() && data->len < 12) {
+				len = 12;
+				memset(dst, 0, 12);
+			}
 			if (sc->sc_cap & CAP_NEEDS_BYTESWAP) {
 				for (i = 0; i < data->len / 4; i++)
 					dst[i] = bswap32(src[i]);
@@ -418,7 +458,7 @@ at91_mci_start_cmd(struct at91_mci_softc
 				memcpy(dst, src, data->len);
 		}
 		data->xfer_len = 0;
-		if (bus_dmamap_load(sc->dmatag, sc->map, vaddr, data->len,
+		if (bus_dmamap_load(sc->dmatag, sc->map, vaddr, len,
 		    at91_mci_getaddr, &paddr, 0) != 0) {
 			cmd->error = MMC_ERR_NO_MEMORY;
 			sc->req = NULL;
@@ -430,12 +470,12 @@ at91_mci_start_cmd(struct at91_mci_softc
 		if (cmdr & MCI_CMDR_TRDIR) {
 			bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_PREREAD);
 			WR4(sc, PDC_RPR, paddr);
-			WR4(sc, PDC_RCR, data->len / 4);
+			WR4(sc, PDC_RCR, len / 4);
 			ier = MCI_SR_ENDRX;
 		} else {
 			bus_dmamap_sync(sc->dmatag, sc->map, BUS_DMASYNC_PREWRITE);
 			WR4(sc, PDC_TPR, paddr);
-			WR4(sc, PDC_TCR, data->len / 4);
+			WR4(sc, PDC_TCR, len / 4);
 			ier = MCI_SR_TXBUFE;
 		}
 	}
@@ -769,7 +809,7 @@ static device_method_t at91_mci_methods[
 	DEVMETHOD(mmcbr_acquire_host, at91_mci_acquire_host),
 	DEVMETHOD(mmcbr_release_host, at91_mci_release_host),
 
-	{0, 0},
+	DEVMETHOD_END
 };
 
 static driver_t at91_mci_driver = {
@@ -777,7 +817,8 @@ static driver_t at91_mci_driver = {
 	at91_mci_methods,
 	sizeof(struct at91_mci_softc),
 };
-static devclass_t at91_mci_devclass;
 
+static devclass_t at91_mci_devclass;
 
-DRIVER_MODULE(at91_mci, atmelarm, at91_mci_driver, at91_mci_devclass, 0, 0);
+DRIVER_MODULE(at91_mci, atmelarm, at91_mci_driver, at91_mci_devclass, NULL,
+    NULL);

Modified: head/sys/arm/at91/at91_mcireg.h
==============================================================================
--- head/sys/arm/at91/at91_mcireg.h	Sat Apr 21 20:22:02 2012	(r234559)
+++ head/sys/arm/at91/at91_mcireg.h	Sun Apr 22 00:43:32 2012	(r234560)
@@ -54,6 +54,9 @@
 /* -------- MCI_MR : (MCI Offset: 0x4) MCI Mode Register --------  */
 #define	MCI_MR_CLKDIV      (0xffu <<  0) /* (MCI) Clock Divider */
 #define	MCI_MR_PWSDIV      (0x3fu <<  8) /* (MCI) Power Saving Divider */
+#define	MCI_MR_RDPROOF	(0x1u << 11)	/* (MCI) Read Proof Enable */
+#define	MCI_MR_WRPROOF	(0x1u << 12)	/* (MCI) Write Proof Enable */
+#define	MCI_MR_PDCFBYTE	(0x1u << 13)	/* (MCI) PDC Force Byte Transfer */
 #define	MCI_MR_PDCPADV     (0x1u << 14) /* (MCI) PDC Padding Value */
 #define	MCI_MR_PDCMODE     (0x1u << 15) /* (MCI) PDC Oriented Mode */
 #define	MCI_MR_BLKLEN      0x3fff0000ul /* (MCI) Data Block Length */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201204220043.q3M0hWT7011795>