Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 28 Sep 2006 19:56:44 GMT
From:      Warner Losh <imp@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 106847 for review
Message-ID:  <200609281956.k8SJuiZX042086@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=106847

Change 106847 by imp@imp_lighthouse on 2006/09/28 19:56:17

	Make non-data command transfers actually work in interrupt mode.
	Oops.

Affected files ...

.. //depot/projects/arm/src/sys/arm/at91/at91_mci.c#9 edit
.. //depot/projects/arm/src/sys/arm/at91/at91_mcireg.h#5 edit

Differences ...

==== //depot/projects/arm/src/sys/arm/at91/at91_mci.c#9 (text+ko) ====

@@ -74,6 +74,7 @@
 	int wire4;
 	int bus_busy;
 	struct mmc_request *req;
+	struct mmc_command *curcmd;
 };
 
 static inline uint32_t
@@ -108,6 +109,20 @@
 #define AT91_MCI_ASSERT_UNLOCKED(_sc) mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
 
 static void
+at91_mci_pdc_disable(struct at91_mci_softc *sc)
+{
+	WR4(sc, PDC_PTCR, PDC_PTCR_TXTDIS | PDC_PTCR_RXTDIS);
+	WR4(sc, PDC_RPR, 0);
+	WR4(sc, PDC_RCR, 0);
+	WR4(sc, PDC_RNPR, 0);
+	WR4(sc, PDC_RNCR, 0);
+	WR4(sc, PDC_TPR, 0);
+	WR4(sc, PDC_TCR, 0);
+	WR4(sc, PDC_TNPR, 0);
+	WR4(sc, PDC_TNCR, 0);
+}
+
+static void
 at91_mci_init(device_t dev)
 {
 	struct at91_mci_softc *sc = device_get_softc(dev);
@@ -125,6 +140,7 @@
 	struct at91_mci_softc *sc = device_get_softc(dev);
 
 	WR4(sc, MCI_IDR, 0xffffffff);		/* Turn off interrupts */
+	at91_mci_pdc_disable(sc);
 	WR4(sc, MCI_CR, MCI_CR_MCIDIS | MCI_CR_SWRST); /* Put the device into reset */
 }
 
@@ -292,7 +308,47 @@
 static void
 at91_mci_start_cmd(struct at91_mci_softc *sc, struct mmc_command *cmd)
 {
-	// XXX
+	uint32_t cmdr;
+
+	sc->curcmd = cmd;
+	cmdr = cmd->opcode;
+	if (MMC_RSP(cmd->flags) == MMC_RSP_NONE)
+		cmdr |= MCI_CMDR_RSPTYP_NO;
+	else {
+		/* Allow big timeout for responses */
+		cmdr |= MCI_CMDR_MAXLAT;
+		if (cmd->flags & MMC_RSP_136)
+			cmdr |= MCI_CMDR_RSPTYP_136;
+		else
+			cmdr |= MCI_CMDR_RSPTYP_48;
+	}
+#if 0
+	if (cmd->data) {
+		if (cmd->data->flags & MMC_DATA_READ)
+			cmdr |= MCI_CMDR_TRDIR;
+		if (cmd->data->flags & (MMC_DATA_READ | MMC_DATA_WRITE))
+			cmdr |= MCI_CMDR_TRCMD_START;
+		if (cmd->data->flags & MMC_DATA_STREAM)
+			cmdr |= MCI_CMDR_TRTYP_STREAM;
+		if (cmd->data->flags & MMC_DATA_MULTI)
+			cmdr |= MCI_CMDR_TRTYP_MULTIPLE;
+		// XXX bad
+	}
+#endif
+	if (cmd->opcode == MMC_STOP_TRANSMISSION)
+		cmdr |= MCI_CMDR_TRCMD_STOP;
+#if 0
+	if (??? == opendrain)
+		cmdr |= MCI_CMDR_OPDCMD;
+#endif
+	if (!cmd->data) {
+		at91_mci_pdc_disable(sc);
+		WR4(sc, MCI_ARGR, cmd->arg);
+		WR4(sc, MCI_CMDR, cmdr);
+		WR4(sc, MCI_IER, MCI_SR_ERROR | MCI_SR_CMDRDY);
+		return;
+	}
+//	panic();
 }
 
 static void
@@ -300,20 +356,26 @@
 {
 	struct mmc_request *req;
 
+	req = sc->req;
 	// assert locked
 	if (!(sc->flags & CMD_STARTED)) {
+		printf("Starting command %d of request %p\n", req->cmd->opcode,
+		    req);
 		sc->flags |= CMD_STARTED;
 		at91_mci_start_cmd(sc, req->cmd);
 		return;
 	}
 	if (!(sc->flags & STOP_STARTED) && req->stop) {
+		printf("Starting command %d of request %p\n", req->stop->opcode,
+		    req);
 		sc->flags |= STOP_STARTED;
 		at91_mci_start_cmd(sc, req->stop);
 		return;
 	}
 	/* We must be done -- bad idea to do this while locked? */
-	req = sc->req;
+	printf("Finished request %p\n", req);
 	sc->req = NULL;
+	sc->curcmd = NULL;
 	req->done(req->done_data);
 }
 
@@ -322,6 +384,7 @@
 {
 	struct at91_mci_softc *sc = device_get_softc(brdev);
 
+	printf("queuing request %p\n", req);
 	AT91_MCI_LOCK(sc);
 	// XXX do we want to be able to queue up multiple commands?
 	// XXX sounds like a good idea, but all protocols are sync, so
@@ -399,10 +462,33 @@
 at91_mci_intr(void *arg)
 {
 	struct at91_mci_softc *sc = (struct at91_mci_softc*)arg;
+	uint32_t sr;
+	int i;
+	struct mmc_command *cmd;
 
 	AT91_MCI_LOCK(sc);
-	printf("i 0x%x\n", RD4(sc, MCI_SR));
-	wakeup(sc);
+	sr = RD4(sc, MCI_SR);
+	printf("i 0x%x\n", sr);
 	WR4(sc, MCI_IDR, 0xffffffff);
+	cmd = sc->curcmd;
+	if (sr & MCI_SR_CMDRDY && cmd != NULL)
+		for (i = 0; i < 4; i++)
+			cmd->resp[i] = RD4(sc, MCI_RSPR + (i << 2));
+	if (sr & MCI_SR_ERROR) {
+		if ((sr & MCI_SR_RCRCE) && (cmd->opcode == MMC_SEND_OP_COND || 
+		    cmd->opcode == ACMD_SD_SEND_OP_COND))
+			cmd->error = MMC_ERR_NONE;
+		else if (sr & (MCI_SR_RTOE | MCI_SR_DTOE))
+			cmd->error = MMC_ERR_TIMEOUT;
+		else if (sr & (MCI_SR_RCRCE | MCI_SR_DCRCE))
+			cmd->error = MMC_ERR_BADCRC;
+		else if (sr & (MCI_SR_OVRE | MCI_SR_UNRE))
+			cmd->error = MMC_ERR_FIFO;
+		else
+			cmd->error = MMC_ERR_FAILED;
+	} else
+		cmd->error = MMC_ERR_NONE;
+
+	at91_mci_start(sc);
 	AT91_MCI_UNLOCK(sc);
 }

==== //depot/projects/arm/src/sys/arm/at91/at91_mcireg.h#5 (text+ko) ====

@@ -94,40 +94,33 @@
 #define		MCI_CMDR_TRTYP_MULTIPLE             (0x1u << 19) /* (MCI) Multiple Block transfer type */
 #define		MCI_CMDR_TRTYP_STREAM               (0x2u << 19) /* (MCI) Stream transfer type */
 /* -------- MCI_SR : (MCI Offset: 0x40) MCI Status Register --------  */
-#define	MCI_SR_CMDRDY      (0x1u <<  0) /* (MCI) Command Ready flag */
-#define	MCI_SR_RXRDY       (0x1u <<  1) /* (MCI) RX Ready flag */
-#define	MCI_SR_TXRDY       (0x1u <<  2) /* (MCI) TX Ready flag */
-#define	MCI_SR_BLKE        (0x1u <<  3) /* (MCI) Data Block Transfer Ended flag */
-#define	MCI_SR_DTIP        (0x1u <<  4) /* (MCI) Data Transfer in Progress flag */
-#define	MCI_SR_NOTBUSY     (0x1u <<  5) /* (MCI) Data Line Not Busy flag */
-#define	MCI_SR_ENDRX       (0x1u <<  6) /* (MCI) End of RX Buffer flag */
-#define	MCI_SR_ENDTX       (0x1u <<  7) /* (MCI) End of TX Buffer flag */
-#define	MCI_SR_RXBUFF      (0x1u << 14) /* (MCI) RX Buffer Full flag */
-#define	MCI_SR_TXBUFE      (0x1u << 15) /* (MCI) TX Buffer Empty flag */
-#define	MCI_SR_RINDE       (0x1u << 16) /* (MCI) Response Index Error flag */
-#define	MCI_SR_RDIRE       (0x1u << 17) /* (MCI) Response Direction Error flag */
-#define	MCI_SR_RCRCE       (0x1u << 18) /* (MCI) Response CRC Error flag */
-#define	MCI_SR_RENDE       (0x1u << 19) /* (MCI) Response End Bit Error flag */
-#define	MCI_SR_RTOE        (0x1u << 20) /* (MCI) Response Time-out Error flag */
-#define	MCI_SR_DCRCE       (0x1u << 21) /* (MCI) data CRC Error flag */
-#define	MCI_SR_DTOE        (0x1u << 22) /* (MCI) Data timeout Error flag */
-#define	MCI_SR_OVRE        (0x1u << 30) /* (MCI) Overrun flag */
-#define	MCI_SR_UNRE        (0x1u << 31) /* (MCI) Underrun flag */
+#define	MCI_SR_CMDRDY   (0x1u <<  0) /* (MCI) Command Ready flag */
+#define	MCI_SR_RXRDY    (0x1u <<  1) /* (MCI) RX Ready flag */
+#define	MCI_SR_TXRDY    (0x1u <<  2) /* (MCI) TX Ready flag */
+#define	MCI_SR_BLKE     (0x1u <<  3) /* (MCI) Data Block Transfer Ended flag */
+#define	MCI_SR_DTIP     (0x1u <<  4) /* (MCI) Data Transfer in Progress flag */
+#define	MCI_SR_NOTBUSY  (0x1u <<  5) /* (MCI) Data Line Not Busy flag */
+#define	MCI_SR_ENDRX    (0x1u <<  6) /* (MCI) End of RX Buffer flag */
+#define	MCI_SR_ENDTX    (0x1u <<  7) /* (MCI) End of TX Buffer flag */
+#define	MCI_SR_RXBUFF   (0x1u << 14) /* (MCI) RX Buffer Full flag */
+#define	MCI_SR_TXBUFE   (0x1u << 15) /* (MCI) TX Buffer Empty flag */
+#define	MCI_SR_RINDE    (0x1u << 16) /* (MCI) Response Index Error flag */
+#define	MCI_SR_RDIRE    (0x1u << 17) /* (MCI) Response Direction Error flag */
+#define	MCI_SR_RCRCE    (0x1u << 18) /* (MCI) Response CRC Error flag */
+#define	MCI_SR_RENDE    (0x1u << 19) /* (MCI) Response End Bit Error flag */
+#define	MCI_SR_RTOE     (0x1u << 20) /* (MCI) Response Time-out Error flag */
+#define	MCI_SR_DCRCE    (0x1u << 21) /* (MCI) data CRC Error flag */
+#define	MCI_SR_DTOE     (0x1u << 22) /* (MCI) Data timeout Error flag */
+#define	MCI_SR_OVRE     (0x1u << 30) /* (MCI) Overrun flag */
+#define	MCI_SR_UNRE     (0x1u << 31) /* (MCI) Underrun flag */
+
 /* -------- MCI_IER : (MCI Offset: 0x44) MCI Interrupt Enable Register --------  */
 /* -------- MCI_IDR : (MCI Offset: 0x48) MCI Interrupt Disable Register --------  */
 /* -------- MCI_IMR : (MCI Offset: 0x4c) MCI Interrupt Mask Register --------  */
 
-#define 	MCI_SR_ERROR		(MCI_SR_UNRE |\
-					 MCI_SR_OVRE |\
-					 MCI_SR_DTOE |\
-					 MCI_SR_DCRCE |\
-					 MCI_SR_RTOE |\
-					 MCI_SR_RENDE |\
-					 MCI_SR_RCRCE |\
-					 MCI_SR_RDIRE |\
-					 MCI_SR_RINDE)
-
-#define AT91C_NO_ARGUMENT			0x0
+#define MCI_SR_ERROR	(MCI_SR_UNRE | MCI_SR_OVRE | MCI_SR_DTOE | \
+			MCI_SR_DCRCE | MCI_SR_RTOE | MCI_SR_RENDE | \
+			MCI_SR_RCRCE | MCI_SR_RDIRE | MCI_SR_RINDE)
 
 #define AT91C_BUS_WIDTH_1BIT		0x00
 #define AT91C_BUS_WIDTH_4BITS		0x02



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