summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/mmc/mmc.c64
-rw-r--r--sys/dev/mmc/mmcbrvar.h4
-rw-r--r--sys/dev/mmc/mmcreg.h9
-rw-r--r--sys/dev/mmc/mmcsd.c42
-rw-r--r--sys/dev/mmc/mmcvar.h3
-rw-r--r--sys/modules/mmcsd/Makefile2
6 files changed, 90 insertions, 34 deletions
diff --git a/sys/dev/mmc/mmc.c b/sys/dev/mmc/mmc.c
index a5dfe92..5771a18 100644
--- a/sys/dev/mmc/mmc.c
+++ b/sys/dev/mmc/mmc.c
@@ -101,6 +101,7 @@ struct mmc_ivars {
uint32_t tran_speed; /* Max speed in normal mode */
uint32_t hs_tran_speed; /* Max speed in high speed mode */
uint32_t erase_sector; /* Card native erase sector size */
+ char card_id_string[64];/* Formatted CID info (serial, MFG, etc) */
};
#define CMD_RETRIES 3
@@ -140,6 +141,7 @@ static void mmc_app_decode_scr(uint32_t *raw_scr, struct mmc_scr *scr);
static int mmc_send_ext_csd(struct mmc_softc *sc, uint8_t *rawextcsd);
static void mmc_scan(struct mmc_softc *sc);
static int mmc_delete_cards(struct mmc_softc *sc);
+static void mmc_format_card_id_string(struct mmc_ivars *ivar);
static void
mmc_ms_delay(int ms)
@@ -606,6 +608,13 @@ mmc_set_card_bus_width(struct mmc_softc *sc, uint16_t rca, int width)
if (mmcbr_get_mode(sc->dev) == mode_sd) {
memset(&cmd, 0, sizeof(struct mmc_command));
+ cmd.opcode = ACMD_SET_CLR_CARD_DETECT;
+ cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
+ cmd.arg = SD_CLR_CARD_DETECT;
+ err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES);
+ if (err != 0)
+ return (err);
+ memset(&cmd, 0, sizeof(struct mmc_command));
cmd.opcode = ACMD_SET_BUS_WIDTH;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
switch (width) {
@@ -788,15 +797,52 @@ mmc_decode_cid_mmc(uint32_t *raw_cid, struct mmc_cid *cid)
cid->mdt_year = mmc_get_bits(raw_cid, 128, 8, 4) + 1997;
}
+static void
+mmc_format_card_id_string(struct mmc_ivars *ivar)
+{
+ char oidstr[8];
+ uint8_t c1;
+ uint8_t c2;
+
+ /*
+ * Format a card ID string for use by the mmcsd driver, it's what
+ * appears between the <> in the following:
+ * mmcsd0: 968MB <SD SD01G 8.0 SN 2686905 Mfg 08/2008 by 3 TN> at mmc0
+ * 22.5MHz/4bit/128-block
+ *
+ * The card_id_string in mmc_ivars is currently allocated as 64 bytes,
+ * and our max formatted length is currently 55 bytes if every field
+ * contains the largest value.
+ *
+ * Sometimes the oid is two printable ascii chars; when it's not,
+ * format it as 0xnnnn instead.
+ */
+ c1 = (ivar->cid.oid >> 8) & 0x0ff;
+ c2 = ivar->cid.oid & 0x0ff;
+ if (c1 > 0x1f && c1 < 0x7f && c2 > 0x1f && c2 < 0x7f)
+ snprintf(oidstr, sizeof(oidstr), "%c%c", c1, c2);
+ else
+ snprintf(oidstr, sizeof(oidstr), "0x%04x", ivar->cid.oid);
+ snprintf(ivar->card_id_string, sizeof(ivar->card_id_string),
+ "%s%s %s %d.%d SN %d MFG %02d/%04d by %d %s",
+ ivar->mode == mode_sd ? "SD" : "MMC", ivar->high_cap ? "HC" : "",
+ ivar->cid.pnm, ivar->cid.prv >> 4, ivar->cid.prv & 0x0f,
+ ivar->cid.psn, ivar->cid.mdt_month, ivar->cid.mdt_year,
+ ivar->cid.mid, oidstr);
+}
+
static const int exp[8] = {
1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
};
+
static const int mant[16] = {
- 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
+ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
};
+
static const int cur_min[8] = {
500, 1000, 5000, 10000, 25000, 35000, 60000, 100000
};
+
static const int cur_max[8] = {
1000, 5000, 10000, 25000, 35000, 45000, 800000, 200000
};
@@ -1080,13 +1126,7 @@ 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, " card: %s\n", ivar->card_id_string);
device_printf(dev, " bus: %ubit, %uMHz%s\n",
(ivar->bus_width == bus_width_1 ? 1 :
(ivar->bus_width == bus_width_4 ? 4 : 8)),
@@ -1188,6 +1228,7 @@ 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;
+ mmc_format_card_id_string(ivar);
if (bootverbose || mmc_debug)
mmc_log_card(sc->dev, ivar, newcard);
if (newcard) {
@@ -1245,6 +1286,7 @@ mmc_discover_cards(struct mmc_softc *sc)
ivar->bus_width = bus_width_1;
ivar->timing = bus_timing_normal;
}
+ mmc_format_card_id_string(ivar);
if (bootverbose || mmc_debug)
mmc_log_card(sc->dev, ivar, newcard);
if (newcard) {
@@ -1477,6 +1519,9 @@ mmc_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
case MMC_IVAR_MAX_DATA:
*result = mmcbr_get_max_data(bus);
break;
+ case MMC_IVAR_CARD_ID_STRING:
+ *(char **)result = ivar->card_id_string;
+ break;
}
return (0);
}
@@ -1527,7 +1572,7 @@ static device_method_t mmc_methods[] = {
DEVMETHOD(mmcbus_acquire_bus, mmc_acquire_bus),
DEVMETHOD(mmcbus_release_bus, mmc_release_bus),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t mmc_driver = {
@@ -1537,6 +1582,5 @@ static driver_t mmc_driver = {
};
static devclass_t mmc_devclass;
-
DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL);
DRIVER_MODULE(mmc, sdhci, mmc_driver, mmc_devclass, NULL, NULL);
diff --git a/sys/dev/mmc/mmcbrvar.h b/sys/dev/mmc/mmcbrvar.h
index 1effa14..9fc1ab8 100644
--- a/sys/dev/mmc/mmcbrvar.h
+++ b/sys/dev/mmc/mmcbrvar.h
@@ -56,6 +56,7 @@
#define DEV_MMC_MMCBRVAR_H
#include <dev/mmc/bridge.h>
+#include <dev/mmc/mmcreg.h>
#include "mmcbr_if.h"
enum mmcbr_device_ivars {
@@ -72,8 +73,7 @@ enum mmcbr_device_ivars {
MMCBR_IVAR_VDD,
MMCBR_IVAR_CAPS,
MMCBR_IVAR_TIMING,
- MMCBR_IVAR_MAX_DATA,
-// MMCBR_IVAR_,
+ MMCBR_IVAR_MAX_DATA
};
/*
diff --git a/sys/dev/mmc/mmcreg.h b/sys/dev/mmc/mmcreg.h
index 8ce9dff..3d2b569 100644
--- a/sys/dev/mmc/mmcreg.h
+++ b/sys/dev/mmc/mmcreg.h
@@ -139,8 +139,8 @@ struct mmc_command {
#define R1_READY_FOR_DATA (1u << 8) /* sx, a */
#define R1_APP_CMD (1u << 5) /* sr, c */
#define R1_AKE_SEQ_ERROR (1u << 3) /* er, c */
-#define R1_STATUS(x) (x & 0xFFFFE000
-#define R1_CURRENT_STATE(x) ((x) & R1_CURRENT_STATE_MASK) >> 9
+#define R1_STATUS(x) ((x) & 0xFFFFE000)
+#define R1_CURRENT_STATE(x) (((x) & R1_CURRENT_STATE_MASK) >> 9)
#define R1_STATE_IDLE 0
#define R1_STATE_READY 1
#define R1_STATE_IDENT 2
@@ -330,6 +330,9 @@ struct mmc_request {
#define SD_SWITCH_HS_MODE 1
#define SD_SWITCH_NOCHANGE 0xF
+#define SD_CLR_CARD_DETECT 0
+#define SD_SET_CARD_DETECT 1
+
#define SD_MAX_HS 50000000
/* OCR bits */
@@ -380,7 +383,7 @@ struct mmc_cid {
uint8_t fwrev;
};
-struct mmc_csd
+struct mmc_csd
{
uint8_t csd_structure;
uint8_t spec_vers;
diff --git a/sys/dev/mmc/mmcsd.c b/sys/dev/mmc/mmcsd.c
index 6dd007c..c3b66db 100644
--- a/sys/dev/mmc/mmcsd.c
+++ b/sys/dev/mmc/mmcsd.c
@@ -66,11 +66,17 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <geom/geom_disk.h>
-#include <dev/mmc/mmcvar.h>
+#include <dev/mmc/mmcbrvar.h>
#include <dev/mmc/mmcreg.h>
+#include <dev/mmc/mmcvar.h>
#include "mmcbus_if.h"
+#if __FreeBSD_version < 800002
+#define kproc_create kthread_create
+#define kproc_exit kthread_exit
+#endif
+
struct mmcsd_softc {
device_t dev;
struct mtx sc_mtx;
@@ -95,7 +101,6 @@ 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);
static int mmcsd_bus_bit_width(device_t dev);
#define MMCSD_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx)
@@ -122,6 +127,8 @@ mmcsd_attach(device_t dev)
struct mmcsd_softc *sc;
struct disk *d;
intmax_t mb;
+ uint32_t speed;
+ uint32_t maxblocks;
char unit;
sc = device_get_softc(dev);
@@ -157,11 +164,22 @@ mmcsd_attach(device_t dev)
unit = 'G';
mb /= 1024;
}
- device_printf(dev, "%ju%cB <%s Memory Card>%s at %s %dMHz/%dbit\n",
- mb, unit, mmcsd_card_name(dev),
+ /*
+ * Report the clock speed of the underlying hardware, which might be
+ * different than what the card reports due to hardware limitations.
+ * Report how many blocks the hardware transfers at once, but clip the
+ * number to MAXPHYS since the system won't initiate larger transfers.
+ */
+ speed = mmcbr_get_clock(device_get_parent(dev));
+ maxblocks = mmc_get_max_data(dev);
+ if (maxblocks > MAXPHYS)
+ maxblocks = MAXPHYS;
+ device_printf(dev, "%ju%cB <%s>%s at %s %d.%01dMHz/%dbit/%d-block\n",
+ mb, unit, mmc_get_card_id_string(dev),
mmc_get_read_only(dev) ? " (read-only)" : "",
device_get_nameunit(device_get_parent(dev)),
- mmc_get_tran_speed(dev) / 1000000, mmcsd_bus_bit_width(dev));
+ speed / 1000000, (speed / 100000) % 10,
+ mmcsd_bus_bit_width(dev), maxblocks);
disk_create(d, DISK_VERSION);
bioq_init(&sc->bio_queue);
@@ -500,16 +518,6 @@ out:
kproc_exit(0);
}
-static const char *
-mmcsd_card_name(device_t dev)
-{
- if (mmc_get_card_type(dev) == mode_mmc)
- return ("MMC");
- if (mmc_get_high_cap(dev))
- return ("SDHC");
- return ("SD");
-}
-
static int
mmcsd_bus_bit_width(device_t dev)
{
@@ -526,7 +534,7 @@ static device_method_t mmcsd_methods[] = {
DEVMETHOD(device_detach, mmcsd_detach),
DEVMETHOD(device_suspend, mmcsd_suspend),
DEVMETHOD(device_resume, mmcsd_resume),
- {0, 0},
+ DEVMETHOD_END
};
static driver_t mmcsd_driver = {
@@ -536,4 +544,4 @@ static driver_t mmcsd_driver = {
};
static devclass_t mmcsd_devclass;
-DRIVER_MODULE(mmcsd, mmc, mmcsd_driver, mmcsd_devclass, 0, 0);
+DRIVER_MODULE(mmcsd, mmc, mmcsd_driver, mmcsd_devclass, NULL, NULL);
diff --git a/sys/dev/mmc/mmcvar.h b/sys/dev/mmc/mmcvar.h
index a28d3ac..b274d32 100644
--- a/sys/dev/mmc/mmcvar.h
+++ b/sys/dev/mmc/mmcvar.h
@@ -69,7 +69,7 @@ enum mmc_device_ivars {
MMC_IVAR_BUS_WIDTH,
MMC_IVAR_ERASE_SECTOR,
MMC_IVAR_MAX_DATA,
-// MMC_IVAR_,
+ MMC_IVAR_CARD_ID_STRING
};
/*
@@ -89,5 +89,6 @@ MMC_ACCESSOR(card_type, CARD_TYPE, int)
MMC_ACCESSOR(bus_width, BUS_WIDTH, int)
MMC_ACCESSOR(erase_sector, ERASE_SECTOR, int)
MMC_ACCESSOR(max_data, MAX_DATA, int)
+MMC_ACCESSOR(card_id_string, CARD_ID_STRING, const char *)
#endif /* DEV_MMC_MMCVAR_H */
diff --git a/sys/modules/mmcsd/Makefile b/sys/modules/mmcsd/Makefile
index 7a02cb2..30ce37d 100644
--- a/sys/modules/mmcsd/Makefile
+++ b/sys/modules/mmcsd/Makefile
@@ -3,6 +3,6 @@
.PATH: ${.CURDIR}/../../dev/mmc
KMOD= mmcsd
-SRCS= mmcsd.c mmcbus_if.h device_if.h bus_if.h
+SRCS= bus_if.h device_if.h mmcbr_if.h mmcbus_if.h mmcsd.c
.include <bsd.kmod.mk>
OpenPOWER on IntegriCloud