svn commit: r188952 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/mmc

Alexander Motin mav at FreeBSD.org
Mon Feb 23 11:52:49 PST 2009


Author: mav
Date: Mon Feb 23 19:52:47 2009
New Revision: 188952
URL: http://svn.freebsd.org/changeset/base/188952

Log:
  MFC rev. 187525 187543 187546 187551 187875 187877 188044 188725
  
  Sync MMC subsystem with HEAD.

Modified:
  stable/7/sys/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)
  stable/7/sys/dev/ath/ath_hal/   (props changed)
  stable/7/sys/dev/cxgb/   (props changed)
  stable/7/sys/dev/mmc/mmc.c
  stable/7/sys/dev/mmc/mmcreg.h
  stable/7/sys/dev/mmc/mmcsd.c

Modified: stable/7/sys/dev/mmc/mmc.c
==============================================================================
--- stable/7/sys/dev/mmc/mmc.c	Mon Feb 23 19:31:48 2009	(r188951)
+++ stable/7/sys/dev/mmc/mmc.c	Mon Feb 23 19:52:47 2009	(r188952)
@@ -62,6 +62,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/mutex.h>
 #include <sys/bus.h>
 #include <sys/endian.h>
+#include <sys/sysctl.h>
 
 #include <dev/mmc/mmcreg.h>
 #include <dev/mmc/mmcbrvar.h>
@@ -104,6 +105,11 @@ struct mmc_ivars {
 
 #define CMD_RETRIES	3
 
+SYSCTL_NODE(_hw, OID_AUTO, mmc, CTLFLAG_RD, NULL, "mmc driver");
+
+static int mmc_debug;
+SYSCTL_INT(_hw_mmc, OID_AUTO, debug, CTLFLAG_RW, &mmc_debug, 0, "Debug level");
+
 /* bus entry points */
 static int mmc_probe(device_t dev);
 static int mmc_attach(device_t dev);
@@ -233,7 +239,7 @@ mmc_acquire_bus(device_t busdev, device_
 			sc->last_rca = rca;
 			/* Prepare bus width for the new card. */
 			ivar = device_get_ivars(dev);
-			if (bootverbose) {
+			if (bootverbose || mmc_debug) {
 				device_printf(busdev,
 				    "setting bus width to %d bits\n",
 				    (ivar->bus_width == bus_width_4) ? 4 :
@@ -315,11 +321,21 @@ mmc_wait_for_req(struct mmc_softc *sc, s
 
 	req->done = mmc_wakeup;
 	req->done_data = sc;
+	if (mmc_debug > 1) {
+		device_printf(sc->dev, "REQUEST: CMD%d arg %#x flags %#x",
+		    req->cmd->opcode, req->cmd->arg, req->cmd->flags);
+		if (req->cmd->data) {
+			printf(" data %d\n", (int)req->cmd->data->len);
+		} else
+			printf("\n");
+	}
 	MMCBR_REQUEST(device_get_parent(sc->dev), sc->dev, req);
 	MMC_LOCK(sc);
 	while ((req->flags & MMC_REQ_DONE) == 0)
 		msleep(req, &sc->sc_mtx, 0, "mmcreq", 0);
 	MMC_UNLOCK(sc);
+	if (mmc_debug > 2 || (mmc_debug > 1 && req->cmd->error))
+		device_printf(sc->dev, "RESULT: %d\n", req->cmd->error);
 	return (0);
 }
 
@@ -340,7 +356,6 @@ mmc_wait_for_cmd(struct mmc_softc *sc, s
 	memset(cmd->resp, 0, sizeof(cmd->resp));
 	cmd->retries = retries;
 	mreq.cmd = cmd;
-/*	printf("CMD: %x ARG %x\n", cmd->opcode, cmd->arg); */
 	mmc_wait_for_req(sc, &mreq);
 	return (cmd->error);
 }
@@ -555,7 +570,8 @@ mmc_switch(struct mmc_softc *sc, uint8_t
 }
 
 static int
-mmc_sd_switch(struct mmc_softc *sc, uint8_t mode, uint8_t grp, uint8_t value, uint8_t *res)
+mmc_sd_switch(struct mmc_softc *sc, uint8_t mode, uint8_t grp, uint8_t value,
+    uint8_t *res)
 {
 	int err;
 	struct mmc_command cmd;
@@ -563,11 +579,11 @@ mmc_sd_switch(struct mmc_softc *sc, uint
 
 	memset(&cmd, 0, sizeof(struct mmc_command));
 	memset(&data, 0, sizeof(struct mmc_data));
-
 	memset(res, 0, 64);
+
 	cmd.opcode = SD_SWITCH_FUNC;
 	cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
-	cmd.arg = mode << 31;
+	cmd.arg = mode << 31;			/* 0 - check, 1 - set */
 	cmd.arg |= 0x00FFFFFF;
 	cmd.arg &= ~(0xF << (grp * 4));
 	cmd.arg |= value << (grp * 4);
@@ -584,11 +600,11 @@ mmc_sd_switch(struct mmc_softc *sc, uint
 static int
 mmc_set_card_bus_width(struct mmc_softc *sc, uint16_t rca, int width)
 {
+	struct mmc_command cmd;
 	int err;
+	uint8_t	value;
 
 	if (mmcbr_get_mode(sc->dev) == mode_sd) {
-		struct mmc_command cmd;
-
 		memset(&cmd, 0, sizeof(struct mmc_command));
 		cmd.opcode = ACMD_SET_BUS_WIDTH;
 		cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
@@ -604,8 +620,6 @@ mmc_set_card_bus_width(struct mmc_softc 
 		}
 		err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES);
 	} else {
-		uint8_t	value;
-
 		switch (width) {
 		case bus_width_1:
 			value = EXT_CSD_BUS_WIDTH_1;
@@ -619,7 +633,8 @@ mmc_set_card_bus_width(struct mmc_softc 
 		default:
 			return (MMC_ERR_INVALID);
 		}
-		err = mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, value);
+		err = mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH,
+		    value);
 	}
 	return (err);
 }
@@ -629,6 +644,7 @@ mmc_set_timing(struct mmc_softc *sc, int
 {
 	int err;
 	uint8_t	value;
+	u_char switch_res[64];
 
 	switch (timing) {
 	case bus_timing_normal:
@@ -640,14 +656,12 @@ mmc_set_timing(struct mmc_softc *sc, int
 	default:
 		return (MMC_ERR_INVALID);
 	}
-	if (mmcbr_get_mode(sc->dev) == mode_sd) {
-		u_char switch_res[64];
-
-		err = mmc_sd_switch(sc, 1, 0, value, switch_res);
-	} else {
+	if (mmcbr_get_mode(sc->dev) == mode_sd)
+		err = mmc_sd_switch(sc, SD_SWITCH_MODE_SET, SD_SWITCH_GROUP1,
+		    value, switch_res);
+	else
 		err = mmc_switch(sc, EXT_CSD_CMD_SET_NORMAL,
 		    EXT_CSD_HS_TIMING, value);
-	}
 	return (err);
 }
 
@@ -749,9 +763,10 @@ mmc_decode_cid_sd(uint32_t *raw_cid, str
 	cid->oid = mmc_get_bits(raw_cid, 128, 104, 16);
 	for (i = 0; i < 5; i++)
 		cid->pnm[i] = mmc_get_bits(raw_cid, 128, 96 - i * 8, 8);
+	cid->pnm[5] = 0;
 	cid->prv = mmc_get_bits(raw_cid, 128, 56, 8);
 	cid->psn = mmc_get_bits(raw_cid, 128, 24, 32);
-	cid->mdt_year = mmc_get_bits(raw_cid, 128, 12, 8) + 2001;
+	cid->mdt_year = mmc_get_bits(raw_cid, 128, 12, 8) + 2000;
 	cid->mdt_month = mmc_get_bits(raw_cid, 128, 8, 4);
 }
 
@@ -766,6 +781,7 @@ mmc_decode_cid_mmc(uint32_t *raw_cid, st
 	cid->oid = mmc_get_bits(raw_cid, 128, 104, 8);
 	for (i = 0; i < 6; i++)
 		cid->pnm[i] = mmc_get_bits(raw_cid, 128, 96 - i * 8, 8);
+	cid->pnm[6] = 0;
 	cid->prv = mmc_get_bits(raw_cid, 128, 48, 8);
 	cid->psn = mmc_get_bits(raw_cid, 128, 16, 32);
 	cid->mdt_month = mmc_get_bits(raw_cid, 128, 12, 4);
@@ -1060,6 +1076,29 @@ mmc_send_relative_addr(struct mmc_softc 
 }
 
 static void
+mmc_log_card(device_t dev, struct mmc_ivars *ivar, int newcard)
+{
+	device_printf(dev, "Card at relative address %d%s:\n",
+	    ivar->rca, newcard ? " added" : "");
+	device_printf(dev, " card: %s%s (0x%x/0x%x/\"%s\" rev %d.%d "
+	    "m/d %02d.%04d s/n %08x)\n",
+	    ivar->mode == mode_sd ? "SD" : "MMC",
+	    ivar->high_cap ? " High Capacity" : "", 
+	    ivar->cid.mid, ivar->cid.oid,
+	    ivar->cid.pnm, ivar->cid.prv >> 4, ivar->cid.prv & 0x0f,
+	    ivar->cid.mdt_month, ivar->cid.mdt_year, ivar->cid.psn);
+	device_printf(dev, " bus: %ubit, %uMHz%s\n",
+	    (ivar->bus_width == bus_width_1 ? 1 :
+	    (ivar->bus_width == bus_width_4 ? 4 : 8)),
+	    (ivar->timing == bus_timing_hs ?
+		ivar->hs_tran_speed : ivar->tran_speed) / 1000000,
+	    ivar->timing == bus_timing_hs ? ", high speed timing" : "");
+	device_printf(dev, " memory: %u blocks, erase sector %u blocks%s\n",
+	    ivar->sec_count, ivar->erase_sector,
+	    ivar->read_only ? ", read-only" : "");
+}
+
+static void
 mmc_discover_cards(struct mmc_softc *sc)
 {
 	struct mmc_ivars *ivar = NULL;
@@ -1071,6 +1110,8 @@ mmc_discover_cards(struct mmc_softc *sc)
 	uint16_t rca = 2;
 	u_char switch_res[64];
 
+	if (bootverbose || mmc_debug)
+		device_printf(sc->dev, "Probing cards\n");
 	while (1) {
 		err = mmc_all_send_cid(sc, raw_cid);
 		if (err == MMC_ERR_TIMEOUT)
@@ -1090,6 +1131,11 @@ mmc_discover_cards(struct mmc_softc *sc)
 			}
 		}
 		free(devlist, M_TEMP);
+		if (bootverbose || mmc_debug) {
+			device_printf(sc->dev, "%sard detected (CID %08x%08x%08x%08x)\n",
+			    newcard ? "New c" : "C",
+			    raw_cid[0], raw_cid[1], raw_cid[2], raw_cid[3]);
+		}
 		if (newcard) {
 			ivar = malloc(sizeof(struct mmc_ivars), M_DEVBUF,
 			    M_WAITOK | M_ZERO);
@@ -1100,6 +1146,7 @@ mmc_discover_cards(struct mmc_softc *sc)
 		if (mmcbr_get_ro(sc->dev))
 			ivar->read_only = 1;
 		ivar->bus_width = bus_width_1;
+		ivar->timing = bus_timing_normal;
 		ivar->mode = mmcbr_get_mode(sc->dev);
 		if (ivar->mode == mode_sd) {
 			mmc_decode_cid_sd(ivar->raw_cid, &ivar->cid);
@@ -1118,13 +1165,15 @@ mmc_discover_cards(struct mmc_softc *sc)
 			mmc_select_card(sc, ivar->rca);
 			mmc_app_send_scr(sc, ivar->rca, ivar->raw_scr);
 			mmc_app_decode_scr(ivar->raw_scr, &ivar->scr);
-			/* Get card switch capabilities. */
+			/* Get card switch capabilities (command class 10). */
 			if ((ivar->scr.sda_vsn >= 1) &&
 			    (ivar->csd.ccc & (1<<10))) {
-				mmc_sd_switch(sc, 0, 0, 0xF, switch_res);
+				mmc_sd_switch(sc, SD_SWITCH_MODE_CHECK,
+				    SD_SWITCH_GROUP1, SD_SWITCH_NOCHANGE,
+				    switch_res);
 				if (switch_res[13] & 2) {
 					ivar->timing = bus_timing_hs;
-					ivar->hs_tran_speed = 50000000;
+					ivar->hs_tran_speed = SD_MAX_HS;
 				}
 			}
 			mmc_app_sd_status(sc, ivar->rca, ivar->raw_sd_status);
@@ -1139,6 +1188,8 @@ mmc_discover_cards(struct mmc_softc *sc)
 			if ((mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) &&
 			    (ivar->scr.bus_widths & SD_SCR_BUS_WIDTH_4))
 				ivar->bus_width = bus_width_4;
+			if (bootverbose || mmc_debug)
+				mmc_log_card(sc->dev, ivar, newcard);
 			if (newcard) {
 				/* Add device. */
 				child = device_add_child(sc->dev, NULL, -1);
@@ -1174,10 +1225,10 @@ mmc_discover_cards(struct mmc_softc *sc)
 			ivar->timing = bus_timing_hs;
 			if (ivar->raw_ext_csd[EXT_CSD_CARD_TYPE]
 			    & EXT_CSD_CARD_TYPE_52)
-				ivar->hs_tran_speed = 52000000;
+				ivar->hs_tran_speed = MMC_TYPE_52_MAX_HS;
 			else if (ivar->raw_ext_csd[EXT_CSD_CARD_TYPE]
 			    & EXT_CSD_CARD_TYPE_26)
-				ivar->hs_tran_speed = 26000000;
+				ivar->hs_tran_speed = MMC_TYPE_26_MAX_HS;
 			else
 				ivar->hs_tran_speed = ivar->tran_speed;
 			/* Find max supported bus width. */
@@ -1194,6 +1245,8 @@ mmc_discover_cards(struct mmc_softc *sc)
 			ivar->bus_width = bus_width_1;
 			ivar->timing = bus_timing_normal;
 		}
+		if (bootverbose || mmc_debug)
+			mmc_log_card(sc->dev, ivar, newcard);
 		if (newcard) {
 			/* Add device. */
 			child = device_add_child(sc->dev, NULL, -1);
@@ -1214,6 +1267,9 @@ mmc_rescan_cards(struct mmc_softc *sc)
 	for (i = 0; i < devcount; i++) {
 		ivar = device_get_ivars(devlist[i]);
 		if (mmc_select_card(sc, ivar->rca)) {
+			if (bootverbose || mmc_debug)
+				device_printf(sc->dev, "Card at relative address %d lost.\n",
+				    ivar->rca);
 			device_delete_child(sc->dev, devlist[i]);
 			free(ivar, M_DEVBUF);
 		}
@@ -1233,6 +1289,9 @@ mmc_delete_cards(struct mmc_softc *sc)
 		return (err);
 	for (i = 0; i < devcount; i++) {
 		ivar = device_get_ivars(devlist[i]);
+		if (bootverbose || mmc_debug)
+			device_printf(sc->dev, "Card at relative address %d deleted.\n",
+			    ivar->rca);
 		device_delete_child(sc->dev, devlist[i]);
 		free(ivar, M_DEVBUF);
 	}
@@ -1255,17 +1314,30 @@ mmc_go_discovery(struct mmc_softc *sc)
 		mmcbr_set_mode(dev, mode_sd);
 		mmc_power_up(sc);
 		mmcbr_set_bus_mode(dev, pushpull);
+		if (bootverbose || mmc_debug)
+			device_printf(sc->dev, "Probing bus\n");
 		mmc_idle_cards(sc);
 		err = mmc_send_if_cond(sc, 1);
+		if ((bootverbose || mmc_debug) && err == 0)
+			device_printf(sc->dev, "SD 2.0 interface conditions: OK\n");
 		if (mmc_send_app_op_cond(sc, err ? 0 : MMC_OCR_CCS, &ocr) !=
 		    MMC_ERR_NONE) {
+			if (bootverbose || mmc_debug)
+				device_printf(sc->dev, "SD probe: failed\n");
 			/*
 			 * Failed, try MMC
 			 */
 			mmcbr_set_mode(dev, mode_mmc);
-			if (mmc_send_op_cond(sc, 0, &ocr) != MMC_ERR_NONE)
+			if (mmc_send_op_cond(sc, 0, &ocr) != MMC_ERR_NONE) {
+				if (bootverbose || mmc_debug)
+					device_printf(sc->dev, "MMC probe: failed\n");
 				ocr = 0; /* Failed both, powerdown. */
-		}
+			} else if (bootverbose || mmc_debug)
+				device_printf(sc->dev,
+				    "MMC probe: OK (OCR: 0x%08x)\n", ocr);
+		} else if (bootverbose || mmc_debug)
+			device_printf(sc->dev, "SD probe: OK (OCR: 0x%08x)\n", ocr);
+
 		mmcbr_set_ocr(dev, mmc_select_vdd(sc, ocr));
 		if (mmcbr_get_ocr(dev) != 0)
 			mmc_idle_cards(sc);
@@ -1279,6 +1351,8 @@ mmc_go_discovery(struct mmc_softc *sc)
 	 * Make sure that we have a mutually agreeable voltage to at least
 	 * one card on the bus.
 	 */
+	if (bootverbose || mmc_debug)
+		device_printf(sc->dev, "Current OCR: 0x%08x\n", mmcbr_get_ocr(dev));
 	if (mmcbr_get_ocr(dev) == 0) {
 		mmc_delete_cards(sc);
 		mmc_power_down(sc);
@@ -1326,7 +1400,7 @@ mmc_calculate_clock(struct mmc_softc *sc
 			max_timing = ivar->timing;
 		if (ivar->tran_speed < max_dtr)
 			max_dtr = ivar->tran_speed;
-		if (ivar->hs_tran_speed < max_dtr)
+		if (ivar->hs_tran_speed < max_hs_dtr)
 			max_hs_dtr = ivar->hs_tran_speed;
 	}
 	for (i = 0; i < nkid; i++) {
@@ -1340,7 +1414,7 @@ mmc_calculate_clock(struct mmc_softc *sc
 	free(kids, M_TEMP);
 	if (max_timing == bus_timing_hs)
 		max_dtr = max_hs_dtr;
-	if (bootverbose) {
+	if (bootverbose || mmc_debug) {
 		device_printf(sc->dev,
 		    "setting transfer rate to %d.%03dMHz%s\n",
 		    max_dtr / 1000000, (max_dtr / 1000) % 1000,
@@ -1454,5 +1528,5 @@ static driver_t mmc_driver = {
 static devclass_t mmc_devclass;
 
 
-DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, 0, 0);
-DRIVER_MODULE(mmc, sdhci, mmc_driver, mmc_devclass, 0, 0);
+DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL);
+DRIVER_MODULE(mmc, sdhci, mmc_driver, mmc_devclass, NULL, NULL);

Modified: stable/7/sys/dev/mmc/mmcreg.h
==============================================================================
--- stable/7/sys/dev/mmc/mmcreg.h	Mon Feb 23 19:31:48 2009	(r188951)
+++ stable/7/sys/dev/mmc/mmcreg.h	Mon Feb 23 19:52:47 2009	(r188952)
@@ -97,6 +97,7 @@ struct mmc_command {
 #define	MMC_ERR_FAILED	4
 #define	MMC_ERR_INVALID	5
 #define	MMC_ERR_NO_MEMORY 6
+#define MMC_ERR_MAX	6
 	struct mmc_data	*data;		/* Data segment with cmd */
 	struct mmc_request *mrq;	/* backpointer to request */
 };
@@ -287,7 +288,6 @@ struct mmc_request {
 /*
  * EXT_CSD fields
  */
-
 #define EXT_CSD_ERASE_GRP_DEF	175	/* R/W */
 #define EXT_CSD_BUS_WIDTH	183	/* R/W */
 #define EXT_CSD_HS_TIMING	185	/* R/W */
@@ -300,7 +300,6 @@ struct mmc_request {
 /*
  * EXT_CSD field definitions
  */
-
 #define EXT_CSD_CMD_SET_NORMAL		1
 #define EXT_CSD_CMD_SET_SECURE		2
 #define EXT_CSD_CMD_SET_CPSECURE	4
@@ -312,12 +311,27 @@ struct mmc_request {
 #define EXT_CSD_BUS_WIDTH_4	1
 #define EXT_CSD_BUS_WIDTH_8	2
 
+#define MMC_TYPE_26_MAX_HS	26000000
+#define MMC_TYPE_52_MAX_HS	52000000
+
 /*
  * SD bus widths
  */
 #define SD_BUS_WIDTH_1		0
 #define SD_BUS_WIDTH_4		2
 
+/*
+ * SD Switch
+ */
+#define SD_SWITCH_MODE_CHECK	0
+#define SD_SWITCH_MODE_SET	1
+#define SD_SWITCH_GROUP1	0
+#define SD_SWITCH_NORMAL_MODE	0
+#define SD_SWITCH_HS_MODE	1
+#define SD_SWITCH_NOCHANGE	0xF
+
+#define	SD_MAX_HS		50000000
+
 /* OCR bits */
 
 /*

Modified: stable/7/sys/dev/mmc/mmcsd.c
==============================================================================
--- stable/7/sys/dev/mmc/mmcsd.c	Mon Feb 23 19:31:48 2009	(r188951)
+++ stable/7/sys/dev/mmc/mmcsd.c	Mon Feb 23 19:52:47 2009	(r188952)
@@ -91,6 +91,8 @@ static int mmcsd_detach(device_t dev);
 static int mmcsd_open(struct disk *dp);
 static int mmcsd_close(struct disk *dp);
 static void mmcsd_strategy(struct bio *bp);
+static int mmcsd_dump(void *arg, void *virtual, vm_offset_t physical,
+	off_t offset, size_t length);
 static void mmcsd_task(void *arg);
 
 static const char *mmcsd_card_name(device_t dev);
@@ -130,7 +132,7 @@ mmcsd_attach(device_t dev)
 	d->d_open = mmcsd_open;
 	d->d_close = mmcsd_close;
 	d->d_strategy = mmcsd_strategy;
-	// d->d_dump = mmcsd_dump;	Need polling mmc layer
+	d->d_dump = mmcsd_dump;
 	d->d_name = "mmcsd";
 	d->d_drv1 = sc;
 	d->d_maxsize = 4*1024*1024;	/* Maximum defined SD card AU size. */
@@ -415,6 +417,33 @@ mmcsd_delete(struct mmcsd_softc *sc, str
 	return (end);
 }
 
+static int
+mmcsd_dump(void *arg, void *virtual, vm_offset_t physical,
+	off_t offset, size_t length)
+{
+	struct disk *disk = arg;
+	struct mmcsd_softc *sc = (struct mmcsd_softc *)disk->d_drv1;
+	device_t dev = sc->dev;
+	struct bio bp;
+	daddr_t block, end;
+
+	/* length zero is special and really means flush buffers to media */
+	if (!length)
+		return (0);
+
+	bzero(&bp, sizeof(struct bio));
+	bp.bio_disk = disk;
+	bp.bio_pblkno = offset / disk->d_sectorsize;
+	bp.bio_bcount = length;
+	bp.bio_data = virtual;
+	bp.bio_cmd = BIO_WRITE;
+	end = bp.bio_pblkno + bp.bio_bcount / sc->disk->d_sectorsize;
+	MMCBUS_ACQUIRE_BUS(device_get_parent(dev), dev);
+	block = mmcsd_rw(sc, &bp);
+	MMCBUS_RELEASE_BUS(device_get_parent(dev), dev);
+	return ((end < block) ? EIO : 0);
+}
+
 static void
 mmcsd_task(void *arg)
 {


More information about the svn-src-stable mailing list