diff options
-rw-r--r-- | sys/dev/mmc/mmc.c | 64 | ||||
-rw-r--r-- | sys/dev/mmc/mmcbrvar.h | 4 | ||||
-rw-r--r-- | sys/dev/mmc/mmcreg.h | 9 | ||||
-rw-r--r-- | sys/dev/mmc/mmcsd.c | 42 | ||||
-rw-r--r-- | sys/dev/mmc/mmcvar.h | 3 | ||||
-rw-r--r-- | sys/modules/mmcsd/Makefile | 2 |
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> |