PERFORCE change 106847 for review
Warner Losh
imp at FreeBSD.org
Thu Sep 28 12:56:48 PDT 2006
http://perforce.freebsd.org/chv.cgi?CH=106847
Change 106847 by imp at 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
More information about the p4-projects
mailing list