svn commit: r333555 - head/sys/arm/allwinner

Emmanuel Vadot manu at FreeBSD.org
Sat May 12 13:13:35 UTC 2018


Author: manu
Date: Sat May 12 13:13:34 2018
New Revision: 333555
URL: https://svnweb.freebsd.org/changeset/base/333555

Log:
  aw_mmc: Do not fully init the controller in attach
  
  Only do a reset of the controller at attach and init it at power_up.
  We use to enable some interrupts in reset, only enable the interrupts
  we are interested in when doing a request.
  While here remove the regulators handling in power_on as it is very wrong
  and will be dealt with in another commit.
  
  Tested on: A31, A64

Modified:
  head/sys/arm/allwinner/aw_mmc.c
  head/sys/arm/allwinner/aw_mmc.h

Modified: head/sys/arm/allwinner/aw_mmc.c
==============================================================================
--- head/sys/arm/allwinner/aw_mmc.c	Sat May 12 13:12:59 2018	(r333554)
+++ head/sys/arm/allwinner/aw_mmc.c	Sat May 12 13:13:34 2018	(r333555)
@@ -140,6 +140,7 @@ static int aw_mmc_attach(device_t);
 static int aw_mmc_detach(device_t);
 static int aw_mmc_setup_dma(struct aw_mmc_softc *);
 static int aw_mmc_reset(struct aw_mmc_softc *);
+static int aw_mmc_init(struct aw_mmc_softc *);
 static void aw_mmc_intr(void *);
 static int aw_mmc_update_clock(struct aw_mmc_softc *, uint32_t);
 
@@ -475,18 +476,37 @@ aw_mmc_reset(struct aw_mmc_softc *sc)
 	if (timeout == 0)
 		return (ETIMEDOUT);
 
+	return (0);
+}
+
+static int
+aw_mmc_init(struct aw_mmc_softc *sc)
+{
+	int ret;
+
+	ret = aw_mmc_reset(sc);
+	if (ret != 0)
+		return (ret);
+
 	/* Set the timeout. */
 	AW_MMC_WRITE_4(sc, AW_MMC_TMOR,
 	    AW_MMC_TMOR_DTO_LMT_SHIFT(AW_MMC_TMOR_DTO_LMT_MASK) |
 	    AW_MMC_TMOR_RTO_LMT_SHIFT(AW_MMC_TMOR_RTO_LMT_MASK));
 
+	/* Unmask interrupts. */
+	AW_MMC_WRITE_4(sc, AW_MMC_IMKR, 0);
+
 	/* Clear pending interrupts. */
 	AW_MMC_WRITE_4(sc, AW_MMC_RISR, 0xffffffff);
+
+	/* Debug register, undocumented */
+	AW_MMC_WRITE_4(sc, AW_MMC_DBGC, 0xdeb);
+
+	/* Function select register */
+	AW_MMC_WRITE_4(sc, AW_MMC_FUNS, 0xceaa0000);
+
 	AW_MMC_WRITE_4(sc, AW_MMC_IDST, 0xffffffff);
-	/* Unmask interrupts. */
-	AW_MMC_WRITE_4(sc, AW_MMC_IMKR,
-	    AW_MMC_INT_CMD_DONE | AW_MMC_INT_ERR_BIT |
-	    AW_MMC_INT_DATA_OVER | AW_MMC_INT_AUTO_STOP_DONE);
+
 	/* Enable interrupts and AHB access. */
 	AW_MMC_WRITE_4(sc, AW_MMC_GCTL,
 	    AW_MMC_READ_4(sc, AW_MMC_GCTL) | AW_MMC_CTRL_INT_ENB);
@@ -655,7 +675,7 @@ aw_mmc_request(device_t bus, device_t child, struct mm
 	int blksz;
 	struct aw_mmc_softc *sc;
 	struct mmc_command *cmd;
-	uint32_t cmdreg;
+	uint32_t cmdreg, imask;
 	int err;
 
 	sc = device_get_softc(bus);
@@ -664,11 +684,19 @@ aw_mmc_request(device_t bus, device_t child, struct mm
 		AW_MMC_UNLOCK(sc);
 		return (EBUSY);
 	}
+
 	sc->aw_req = req;
 	cmd = req->cmd;
 	cmdreg = AW_MMC_CMDR_LOAD;
+	imask = AW_MMC_INT_ERR_BIT;
+	sc->aw_intr_wait = 0;
+	sc->aw_intr = 0;
+	sc->aw_resid = 0;
+	cmd->error = MMC_ERR_NONE;
+
 	if (cmd->opcode == MMC_GO_IDLE_STATE)
 		cmdreg |= AW_MMC_CMDR_SEND_INIT_SEQ;
+
 	if (cmd->flags & MMC_RSP_PRESENT)
 		cmdreg |= AW_MMC_CMDR_RESP_RCV;
 	if (cmd->flags & MMC_RSP_136)
@@ -676,30 +704,52 @@ aw_mmc_request(device_t bus, device_t child, struct mm
 	if (cmd->flags & MMC_RSP_CRC)
 		cmdreg |= AW_MMC_CMDR_CHK_RESP_CRC;
 
-	sc->aw_intr = 0;
-	sc->aw_resid = 0;
-	sc->aw_intr_wait = AW_MMC_INT_CMD_DONE;
-	cmd->error = MMC_ERR_NONE;
-	if (cmd->data != NULL) {
-		sc->aw_intr_wait |= AW_MMC_INT_DATA_OVER;
+	if (cmd->data) {
 		cmdreg |= AW_MMC_CMDR_DATA_TRANS | AW_MMC_CMDR_WAIT_PRE_OVER;
+
 		if (cmd->data->flags & MMC_DATA_MULTI) {
 			cmdreg |= AW_MMC_CMDR_STOP_CMD_FLAG;
+			imask |= AW_MMC_INT_AUTO_STOP_DONE;
 			sc->aw_intr_wait |= AW_MMC_INT_AUTO_STOP_DONE;
+		} else {
+			sc->aw_intr_wait |= AW_MMC_INT_DATA_OVER;
+			imask |= AW_MMC_INT_DATA_OVER;
 		}
 		if (cmd->data->flags & MMC_DATA_WRITE)
 			cmdreg |= AW_MMC_CMDR_DIR_WRITE;
+
 		blksz = min(cmd->data->len, MMC_SECTOR_SIZE);
 		AW_MMC_WRITE_4(sc, AW_MMC_BKSR, blksz);
 		AW_MMC_WRITE_4(sc, AW_MMC_BYCR, cmd->data->len);
+	} else {
+		imask |= AW_MMC_INT_CMD_DONE;
+	}
 
+	/* Enable the interrupts we are interested in */
+	AW_MMC_WRITE_4(sc, AW_MMC_IMKR, imask);
+	AW_MMC_WRITE_4(sc, AW_MMC_RISR, 0xffffffff);
+
+	/* Enable auto stop if needed */
+	AW_MMC_WRITE_4(sc, AW_MMC_A12A,
+	    cmdreg & AW_MMC_CMDR_STOP_CMD_FLAG ? 0 : 0xffff);
+
+	/* Write the command argument */
+	AW_MMC_WRITE_4(sc, AW_MMC_CAGR, cmd->arg);
+
+	/* 
+	 * If we don't have data start the request
+	 * if we do prepare the dma request and start the request
+	 */
+	if (cmd->data == NULL) {
+		AW_MMC_WRITE_4(sc, AW_MMC_CMDR, cmdreg | cmd->opcode);
+	} else {
 		err = aw_mmc_prepare_dma(sc);
 		if (err != 0)
 			device_printf(sc->aw_dev, "prepare_dma failed: %d\n", err);
+
+		AW_MMC_WRITE_4(sc, AW_MMC_CMDR, cmdreg | cmd->opcode);
 	}
 
-	AW_MMC_WRITE_4(sc, AW_MMC_CAGR, cmd->arg);
-	AW_MMC_WRITE_4(sc, AW_MMC_CMDR, cmdreg | cmd->opcode);
 	callout_reset(&sc->aw_timeoutc, sc->aw_timeout * hz,
 	    aw_mmc_timeout, sc);
 	AW_MMC_UNLOCK(sc);
@@ -914,16 +964,20 @@ aw_mmc_update_ios(device_t bus, device_t child)
 		break;
 	}
 
-	/* Set the voltage */
-	if (ios->power_mode == power_off) {
+	switch (ios->power_mode) {
+	case power_on:
+		break;
+	case power_off:
 		if (bootverbose)
 			device_printf(sc->aw_dev, "Powering down sd/mmc\n");
-		if (sc->aw_reg_vmmc)
-			regulator_disable(sc->aw_reg_vmmc);
-		if (sc->aw_reg_vqmmc)
-			regulator_disable(sc->aw_reg_vqmmc);
-	} else if (sc->aw_vdd != ios->vdd)
-		aw_mmc_set_power(sc, ios->vdd);
+		aw_mmc_reset(sc);
+		break;
+	case power_up:
+		if (bootverbose)
+			device_printf(sc->aw_dev, "Powering up sd/mmc\n");
+		aw_mmc_init(sc);
+		break;
+	};
 
 	/* Enable ddr mode if needed */
 	reg = AW_MMC_READ_4(sc, AW_MMC_GCTL);

Modified: head/sys/arm/allwinner/aw_mmc.h
==============================================================================
--- head/sys/arm/allwinner/aw_mmc.h	Sat May 12 13:12:59 2018	(r333554)
+++ head/sys/arm/allwinner/aw_mmc.h	Sat May 12 13:13:34 2018	(r333555)
@@ -47,6 +47,7 @@
 #define	AW_MMC_STAR		0x3C	/* Status Register */
 #define	AW_MMC_FWLR		0x40	/* FIFO Threshold Watermark Register */
 #define	AW_MMC_FUNS		0x44	/* Function Select Register */
+#define	AW_MMC_DBGC		0x50	/* Debug register */
 #define	AW_MMC_CSDC		0x54	/* CRC status detect controler register (A64 smhc2 only) */
 #define	AW_MMC_A12A		0x58	/* Auto command 12 argument register */
 #define	AW_MMC_NTSR		0x5C	/* SD new timing register (H3, A64 smhc0/1 only) */


More information about the svn-src-all mailing list