mmc: Update to FreeBSD trunk 2016-08-23

This commit is contained in:
Sebastian Huber 2016-08-23 14:22:26 +02:00
parent a971614a91
commit 0c24e06130
7 changed files with 241 additions and 112 deletions

View File

@ -54,6 +54,8 @@
#ifndef DEV_MMC_BRIDGE_H #ifndef DEV_MMC_BRIDGE_H
#define DEV_MMC_BRIDGE_H #define DEV_MMC_BRIDGE_H
#include <sys/bus.h>
/* /*
* This file defines interfaces for the mmc bridge. The names chosen * This file defines interfaces for the mmc bridge. The names chosen
* are similar to or the same as the names used in Linux to allow for * are similar to or the same as the names used in Linux to allow for
@ -135,4 +137,7 @@ struct mmc_host {
struct mmc_ios ios; /* Current state of the host */ struct mmc_ios ios; /* Current state of the host */
}; };
extern driver_t mmc_driver;
extern devclass_t mmc_devclass;
#endif /* DEV_MMC_BRIDGE_H */ #endif /* DEV_MMC_BRIDGE_H */

View File

@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
#include <sys/bus.h> #include <sys/bus.h>
#include <sys/endian.h> #include <sys/endian.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
#include <sys/time.h>
#include <dev/mmc/mmcreg.h> #include <dev/mmc/mmcreg.h>
#include <dev/mmc/mmcbrvar.h> #include <dev/mmc/mmcbrvar.h>
@ -78,8 +79,13 @@ struct mmc_softc {
struct intr_config_hook config_intrhook; struct intr_config_hook config_intrhook;
device_t owner; device_t owner;
uint32_t last_rca; uint32_t last_rca;
int squelched; /* suppress reporting of (expected) errors */
int log_count;
struct timeval log_time;
}; };
#define LOG_PPS 5 /* Log no more than 5 errors per second. */
/* /*
* Per-card data * Per-card data
*/ */
@ -104,14 +110,17 @@ struct mmc_ivars {
uint32_t hs_tran_speed; /* Max speed in high speed mode */ uint32_t hs_tran_speed; /* Max speed in high speed mode */
uint32_t erase_sector; /* Card native erase sector size */ uint32_t erase_sector; /* Card native erase sector size */
char card_id_string[64];/* Formatted CID info (serial, MFG, etc) */ char card_id_string[64];/* Formatted CID info (serial, MFG, etc) */
char card_sn_string[16];/* Formatted serial # for disk->d_ident */
}; };
#define CMD_RETRIES 3 #define CMD_RETRIES 3
#define CARD_ID_FREQUENCY 400000 /* Spec requires 400kHz max during ID phase. */
static SYSCTL_NODE(_hw, OID_AUTO, mmc, CTLFLAG_RD, NULL, "mmc driver"); static SYSCTL_NODE(_hw, OID_AUTO, mmc, CTLFLAG_RD, NULL, "mmc driver");
static int mmc_debug; static int mmc_debug;
SYSCTL_INT(_hw_mmc, OID_AUTO, debug, CTLFLAG_RW, &mmc_debug, 0, "Debug level"); SYSCTL_INT(_hw_mmc, OID_AUTO, debug, CTLFLAG_RWTUN, &mmc_debug, 0, "Debug level");
/* bus entry points */ /* bus entry points */
static int mmc_acquire_bus(device_t busdev, device_t dev); static int mmc_acquire_bus(device_t busdev, device_t dev);
@ -355,7 +364,8 @@ mmc_highest_voltage(uint32_t ocr)
{ {
int i; int i;
for (i = 30; i >= 0; i--) for (i = MMC_OCR_MAX_VOLTAGE_SHIFT;
i >= MMC_OCR_MIN_VOLTAGE_SHIFT; i--)
if (ocr & (1 << i)) if (ocr & (1 << i))
return (i); return (i);
return (-1); return (-1);
@ -392,8 +402,9 @@ mmc_wait_for_req(struct mmc_softc *sc, struct mmc_request *req)
while ((req->flags & MMC_REQ_DONE) == 0) while ((req->flags & MMC_REQ_DONE) == 0)
msleep(req, &sc->sc_mtx, 0, "mmcreq", 0); msleep(req, &sc->sc_mtx, 0, "mmcreq", 0);
MMC_UNLOCK(sc); MMC_UNLOCK(sc);
if (mmc_debug > 2 || (mmc_debug > 1 && req->cmd->error)) if (mmc_debug > 2 || (mmc_debug > 0 && req->cmd->error != MMC_ERR_NONE))
device_printf(sc->dev, "RESULT: %d\n", req->cmd->error); device_printf(sc->dev, "CMD%d RESULT: %d\n",
req->cmd->opcode, req->cmd->error);
return (0); return (0);
} }
@ -409,13 +420,28 @@ static int
mmc_wait_for_cmd(struct mmc_softc *sc, struct mmc_command *cmd, int retries) mmc_wait_for_cmd(struct mmc_softc *sc, struct mmc_command *cmd, int retries)
{ {
struct mmc_request mreq; struct mmc_request mreq;
int err;
do {
memset(&mreq, 0, sizeof(mreq)); memset(&mreq, 0, sizeof(mreq));
memset(cmd->resp, 0, sizeof(cmd->resp)); memset(cmd->resp, 0, sizeof(cmd->resp));
cmd->retries = retries; cmd->retries = 0; /* Retries done here, not in hardware. */
cmd->mrq = &mreq;
mreq.cmd = cmd; mreq.cmd = cmd;
mmc_wait_for_req(sc, &mreq); if (mmc_wait_for_req(sc, &mreq) != 0)
return (cmd->error); err = MMC_ERR_FAILED;
else
err = cmd->error;
} while (err != MMC_ERR_NONE && retries-- > 0);
if (err != MMC_ERR_NONE && sc->squelched == 0) {
if (ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) {
device_printf(sc->dev, "CMD%d failed, RESULT: %d\n",
cmd->opcode, err);
}
}
return (err);
} }
static int static int
@ -423,24 +449,38 @@ mmc_wait_for_app_cmd(struct mmc_softc *sc, uint32_t rca,
struct mmc_command *cmd, int retries) struct mmc_command *cmd, int retries)
{ {
struct mmc_command appcmd; struct mmc_command appcmd;
int err = MMC_ERR_NONE, i; int err;
for (i = 0; i <= retries; i++) { /* Squelch error reporting at lower levels, we report below. */
sc->squelched++;
do {
memset(&appcmd, 0, sizeof(appcmd));
appcmd.opcode = MMC_APP_CMD; appcmd.opcode = MMC_APP_CMD;
appcmd.arg = rca << 16; appcmd.arg = rca << 16;
appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC; appcmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
appcmd.data = NULL; appcmd.data = NULL;
mmc_wait_for_cmd(sc, &appcmd, 0); if (mmc_wait_for_cmd(sc, &appcmd, 0) != 0)
err = MMC_ERR_FAILED;
else
err = appcmd.error; err = appcmd.error;
if (err != MMC_ERR_NONE) if (err == MMC_ERR_NONE) {
continue;
if (!(appcmd.resp[0] & R1_APP_CMD)) if (!(appcmd.resp[0] & R1_APP_CMD))
return MMC_ERR_FAILED; err = MMC_ERR_FAILED;
mmc_wait_for_cmd(sc, cmd, 0); else if (mmc_wait_for_cmd(sc, cmd, 0) != 0)
err = MMC_ERR_FAILED;
else
err = cmd->error; err = cmd->error;
if (err == MMC_ERR_NONE)
break;
} }
} while (err != MMC_ERR_NONE && retries-- > 0);
sc->squelched--;
if (err != MMC_ERR_NONE && sc->squelched == 0) {
if (ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) {
device_printf(sc->dev, "ACMD%d failed, RESULT: %d\n",
cmd->opcode, err);
}
}
return (err); return (err);
} }
@ -459,8 +499,6 @@ mmc_wait_for_command(struct mmc_softc *sc, uint32_t opcode,
err = mmc_wait_for_cmd(sc, &cmd, retries); err = mmc_wait_for_cmd(sc, &cmd, retries);
if (err) if (err)
return (err); return (err);
if (cmd.error)
return (cmd.error);
if (resp) { if (resp) {
if (flags & MMC_RSP_136) if (flags & MMC_RSP_136)
memcpy(resp, cmd.resp, 4 * sizeof(uint32_t)); memcpy(resp, cmd.resp, 4 * sizeof(uint32_t));
@ -486,7 +524,7 @@ mmc_idle_cards(struct mmc_softc *sc)
cmd.arg = 0; cmd.arg = 0;
cmd.flags = MMC_RSP_NONE | MMC_CMD_BC; cmd.flags = MMC_RSP_NONE | MMC_CMD_BC;
cmd.data = NULL; cmd.data = NULL;
mmc_wait_for_cmd(sc, &cmd, 0); mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
mmc_ms_delay(1); mmc_ms_delay(1);
mmcbr_set_chip_select(dev, cs_dontcare); mmcbr_set_chip_select(dev, cs_dontcare);
@ -579,7 +617,7 @@ mmc_power_up(struct mmc_softc *sc)
mmcbr_update_ios(dev); mmcbr_update_ios(dev);
mmc_ms_delay(1); mmc_ms_delay(1);
mmcbr_set_clock(dev, mmcbr_get_f_min(sc->dev)); mmcbr_set_clock(dev, CARD_ID_FREQUENCY);
mmcbr_set_timing(dev, bus_timing_normal); mmcbr_set_timing(dev, bus_timing_normal);
mmcbr_set_power_mode(dev, power_on); mmcbr_set_power_mode(dev, power_on);
mmcbr_update_ios(dev); mmcbr_update_ios(dev);
@ -616,6 +654,7 @@ mmc_switch(struct mmc_softc *sc, uint8_t set, uint8_t index, uint8_t value)
struct mmc_command cmd; struct mmc_command cmd;
int err; int err;
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = MMC_SWITCH_FUNC; cmd.opcode = MMC_SWITCH_FUNC;
cmd.arg = (MMC_SWITCH_FUNC_WR << 24) | cmd.arg = (MMC_SWITCH_FUNC_WR << 24) |
(index << 16) | (index << 16) |
@ -623,7 +662,7 @@ mmc_switch(struct mmc_softc *sc, uint8_t set, uint8_t index, uint8_t value)
set; set;
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
cmd.data = NULL; cmd.data = NULL;
err = mmc_wait_for_cmd(sc, &cmd, 0); err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
return (err); return (err);
} }
@ -635,8 +674,8 @@ mmc_sd_switch(struct mmc_softc *sc, uint8_t mode, uint8_t grp, uint8_t value,
struct mmc_command cmd; struct mmc_command cmd;
struct mmc_data data; struct mmc_data data;
memset(&cmd, 0, sizeof(struct mmc_command)); memset(&cmd, 0, sizeof(cmd));
memset(&data, 0, sizeof(struct mmc_data)); memset(&data, 0, sizeof(data));
memset(res, 0, 64); memset(res, 0, 64);
cmd.opcode = SD_SWITCH_FUNC; cmd.opcode = SD_SWITCH_FUNC;
@ -663,14 +702,14 @@ mmc_set_card_bus_width(struct mmc_softc *sc, uint16_t rca, int width)
uint8_t value; uint8_t value;
if (mmcbr_get_mode(sc->dev) == mode_sd) { if (mmcbr_get_mode(sc->dev) == mode_sd) {
memset(&cmd, 0, sizeof(struct mmc_command)); memset(&cmd, 0, sizeof(cmd));
cmd.opcode = ACMD_SET_CLR_CARD_DETECT; cmd.opcode = ACMD_SET_CLR_CARD_DETECT;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
cmd.arg = SD_CLR_CARD_DETECT; cmd.arg = SD_CLR_CARD_DETECT;
err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES); err = mmc_wait_for_app_cmd(sc, rca, &cmd, CMD_RETRIES);
if (err != 0) if (err != 0)
return (err); return (err);
memset(&cmd, 0, sizeof(struct mmc_command)); memset(&cmd, 0, sizeof(cmd));
cmd.opcode = ACMD_SET_BUS_WIDTH; cmd.opcode = ACMD_SET_BUS_WIDTH;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
switch (width) { switch (width) {
@ -746,6 +785,9 @@ mmc_test_bus_width(struct mmc_softc *sc)
mmcbr_set_bus_width(sc->dev, bus_width_8); mmcbr_set_bus_width(sc->dev, bus_width_8);
mmcbr_update_ios(sc->dev); mmcbr_update_ios(sc->dev);
sc->squelched++; /* Errors are expected, squelch reporting. */
memset(&cmd, 0, sizeof(cmd));
memset(&data, 0, sizeof(data));
cmd.opcode = MMC_BUSTEST_W; cmd.opcode = MMC_BUSTEST_W;
cmd.arg = 0; cmd.arg = 0;
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
@ -756,6 +798,8 @@ mmc_test_bus_width(struct mmc_softc *sc)
data.flags = MMC_DATA_WRITE; data.flags = MMC_DATA_WRITE;
mmc_wait_for_cmd(sc, &cmd, 0); mmc_wait_for_cmd(sc, &cmd, 0);
memset(&cmd, 0, sizeof(cmd));
memset(&data, 0, sizeof(data));
cmd.opcode = MMC_BUSTEST_R; cmd.opcode = MMC_BUSTEST_R;
cmd.arg = 0; cmd.arg = 0;
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
@ -765,6 +809,7 @@ mmc_test_bus_width(struct mmc_softc *sc)
data.len = 8; data.len = 8;
data.flags = MMC_DATA_READ; data.flags = MMC_DATA_READ;
err = mmc_wait_for_cmd(sc, &cmd, 0); err = mmc_wait_for_cmd(sc, &cmd, 0);
sc->squelched--;
mmcbr_set_bus_width(sc->dev, bus_width_1); mmcbr_set_bus_width(sc->dev, bus_width_1);
mmcbr_update_ios(sc->dev); mmcbr_update_ios(sc->dev);
@ -777,6 +822,9 @@ mmc_test_bus_width(struct mmc_softc *sc)
mmcbr_set_bus_width(sc->dev, bus_width_4); mmcbr_set_bus_width(sc->dev, bus_width_4);
mmcbr_update_ios(sc->dev); mmcbr_update_ios(sc->dev);
sc->squelched++; /* Errors are expected, squelch reporting. */
memset(&cmd, 0, sizeof(cmd));
memset(&data, 0, sizeof(data));
cmd.opcode = MMC_BUSTEST_W; cmd.opcode = MMC_BUSTEST_W;
cmd.arg = 0; cmd.arg = 0;
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
@ -787,6 +835,8 @@ mmc_test_bus_width(struct mmc_softc *sc)
data.flags = MMC_DATA_WRITE; data.flags = MMC_DATA_WRITE;
mmc_wait_for_cmd(sc, &cmd, 0); mmc_wait_for_cmd(sc, &cmd, 0);
memset(&cmd, 0, sizeof(cmd));
memset(&data, 0, sizeof(data));
cmd.opcode = MMC_BUSTEST_R; cmd.opcode = MMC_BUSTEST_R;
cmd.arg = 0; cmd.arg = 0;
cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC;
@ -796,6 +846,7 @@ mmc_test_bus_width(struct mmc_softc *sc)
data.len = 4; data.len = 4;
data.flags = MMC_DATA_READ; data.flags = MMC_DATA_READ;
err = mmc_wait_for_cmd(sc, &cmd, 0); err = mmc_wait_for_cmd(sc, &cmd, 0);
sc->squelched--;
mmcbr_set_bus_width(sc->dev, bus_width_1); mmcbr_set_bus_width(sc->dev, bus_width_1);
mmcbr_update_ios(sc->dev); mmcbr_update_ios(sc->dev);
@ -866,6 +917,9 @@ mmc_format_card_id_string(struct mmc_ivars *ivar)
* mmcsd0: 968MB <SD SD01G 8.0 SN 2686905 Mfg 08/2008 by 3 TN> at mmc0 * mmcsd0: 968MB <SD SD01G 8.0 SN 2686905 Mfg 08/2008 by 3 TN> at mmc0
* 22.5MHz/4bit/128-block * 22.5MHz/4bit/128-block
* *
* Also format just the card serial number, which the mmcsd driver will
* use as the disk->d_ident string.
*
* The card_id_string in mmc_ivars is currently allocated as 64 bytes, * 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 * and our max formatted length is currently 55 bytes if every field
* contains the largest value. * contains the largest value.
@ -879,8 +933,10 @@ mmc_format_card_id_string(struct mmc_ivars *ivar)
snprintf(oidstr, sizeof(oidstr), "%c%c", c1, c2); snprintf(oidstr, sizeof(oidstr), "%c%c", c1, c2);
else else
snprintf(oidstr, sizeof(oidstr), "0x%04x", ivar->cid.oid); snprintf(oidstr, sizeof(oidstr), "0x%04x", ivar->cid.oid);
snprintf(ivar->card_sn_string, sizeof(ivar->card_sn_string),
"%08X", ivar->cid.psn);
snprintf(ivar->card_id_string, sizeof(ivar->card_id_string), snprintf(ivar->card_id_string, sizeof(ivar->card_id_string),
"%s%s %s %d.%d SN %u MFG %02d/%04d by %d %s", "%s%s %s %d.%d SN %08X MFG %02d/%04d by %d %s",
ivar->mode == mode_sd ? "SD" : "MMC", ivar->high_cap ? "HC" : "", ivar->mode == mode_sd ? "SD" : "MMC", ivar->high_cap ? "HC" : "",
ivar->cid.pnm, ivar->cid.prv >> 4, ivar->cid.prv & 0x0f, ivar->cid.pnm, ivar->cid.prv >> 4, ivar->cid.prv & 0x0f,
ivar->cid.psn, ivar->cid.mdt_month, ivar->cid.mdt_year, ivar->cid.psn, ivar->cid.mdt_month, ivar->cid.mdt_year,
@ -1048,11 +1104,12 @@ mmc_all_send_cid(struct mmc_softc *sc, uint32_t *rawcid)
struct mmc_command cmd; struct mmc_command cmd;
int err; int err;
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = MMC_ALL_SEND_CID; cmd.opcode = MMC_ALL_SEND_CID;
cmd.arg = 0; cmd.arg = 0;
cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR; cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
cmd.data = NULL; cmd.data = NULL;
err = mmc_wait_for_cmd(sc, &cmd, 0); err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
memcpy(rawcid, cmd.resp, 4 * sizeof(uint32_t)); memcpy(rawcid, cmd.resp, 4 * sizeof(uint32_t));
return (err); return (err);
} }
@ -1063,11 +1120,12 @@ mmc_send_csd(struct mmc_softc *sc, uint16_t rca, uint32_t *rawcsd)
struct mmc_command cmd; struct mmc_command cmd;
int err; int err;
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = MMC_SEND_CSD; cmd.opcode = MMC_SEND_CSD;
cmd.arg = rca << 16; cmd.arg = rca << 16;
cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR; cmd.flags = MMC_RSP_R2 | MMC_CMD_BCR;
cmd.data = NULL; cmd.data = NULL;
err = mmc_wait_for_cmd(sc, &cmd, 0); err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
memcpy(rawcsd, cmd.resp, 4 * sizeof(uint32_t)); memcpy(rawcsd, cmd.resp, 4 * sizeof(uint32_t));
return (err); return (err);
} }
@ -1079,8 +1137,8 @@ mmc_app_send_scr(struct mmc_softc *sc, uint16_t rca, uint32_t *rawscr)
struct mmc_command cmd; struct mmc_command cmd;
struct mmc_data data; struct mmc_data data;
memset(&cmd, 0, sizeof(struct mmc_command)); memset(&cmd, 0, sizeof(cmd));
memset(&data, 0, sizeof(struct mmc_data)); memset(&data, 0, sizeof(data));
memset(rawscr, 0, 8); memset(rawscr, 0, 8);
cmd.opcode = ACMD_SEND_SCR; cmd.opcode = ACMD_SEND_SCR;
@ -1105,8 +1163,8 @@ mmc_send_ext_csd(struct mmc_softc *sc, uint8_t *rawextcsd)
struct mmc_command cmd; struct mmc_command cmd;
struct mmc_data data; struct mmc_data data;
memset(&cmd, 0, sizeof(struct mmc_command)); memset(&cmd, 0, sizeof(cmd));
memset(&data, 0, sizeof(struct mmc_data)); memset(&data, 0, sizeof(data));
memset(rawextcsd, 0, 512); memset(rawextcsd, 0, 512);
cmd.opcode = MMC_SEND_EXT_CSD; cmd.opcode = MMC_SEND_EXT_CSD;
@ -1129,8 +1187,8 @@ mmc_app_sd_status(struct mmc_softc *sc, uint16_t rca, uint32_t *rawsdstatus)
struct mmc_command cmd; struct mmc_command cmd;
struct mmc_data data; struct mmc_data data;
memset(&cmd, 0, sizeof(struct mmc_command)); memset(&cmd, 0, sizeof(cmd));
memset(&data, 0, sizeof(struct mmc_data)); memset(&data, 0, sizeof(data));
memset(rawsdstatus, 0, 64); memset(rawsdstatus, 0, 64);
cmd.opcode = ACMD_SD_STATUS; cmd.opcode = ACMD_SD_STATUS;
@ -1154,11 +1212,12 @@ mmc_set_relative_addr(struct mmc_softc *sc, uint16_t resp)
struct mmc_command cmd; struct mmc_command cmd;
int err; int err;
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = MMC_SET_RELATIVE_ADDR; cmd.opcode = MMC_SET_RELATIVE_ADDR;
cmd.arg = resp << 16; cmd.arg = resp << 16;
cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR; cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
cmd.data = NULL; cmd.data = NULL;
err = mmc_wait_for_cmd(sc, &cmd, 0); err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
return (err); return (err);
} }
@ -1168,11 +1227,12 @@ mmc_send_relative_addr(struct mmc_softc *sc, uint32_t *resp)
struct mmc_command cmd; struct mmc_command cmd;
int err; int err;
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = SD_SEND_RELATIVE_ADDR; cmd.opcode = SD_SEND_RELATIVE_ADDR;
cmd.arg = 0; cmd.arg = 0;
cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR; cmd.flags = MMC_RSP_R6 | MMC_CMD_BCR;
cmd.data = NULL; cmd.data = NULL;
err = mmc_wait_for_cmd(sc, &cmd, 0); err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
*resp = cmd.resp[0]; *resp = cmd.resp[0];
return (err); return (err);
} }
@ -1183,11 +1243,12 @@ mmc_send_status(struct mmc_softc *sc, uint16_t rca, uint32_t *status)
struct mmc_command cmd; struct mmc_command cmd;
int err; int err;
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = MMC_SEND_STATUS; cmd.opcode = MMC_SEND_STATUS;
cmd.arg = rca << 16; cmd.arg = rca << 16;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
cmd.data = NULL; cmd.data = NULL;
err = mmc_wait_for_cmd(sc, &cmd, 0); err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
*status = cmd.resp[0]; *status = cmd.resp[0];
return (err); return (err);
} }
@ -1198,18 +1259,19 @@ mmc_set_blocklen(struct mmc_softc *sc, uint32_t len)
struct mmc_command cmd; struct mmc_command cmd;
int err; int err;
memset(&cmd, 0, sizeof(cmd));
cmd.opcode = MMC_SET_BLOCKLEN; cmd.opcode = MMC_SET_BLOCKLEN;
cmd.arg = len; cmd.arg = len;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
cmd.data = NULL; cmd.data = NULL;
err = mmc_wait_for_cmd(sc, &cmd, 0); err = mmc_wait_for_cmd(sc, &cmd, CMD_RETRIES);
return (err); return (err);
} }
static void static void
mmc_log_card(device_t dev, struct mmc_ivars *ivar, int newcard) mmc_log_card(device_t dev, struct mmc_ivars *ivar, int newcard)
{ {
device_printf(dev, "Card at relative address %d%s:\n", device_printf(dev, "Card at relative address 0x%04x%s:\n",
ivar->rca, newcard ? " added" : ""); ivar->rca, newcard ? " added" : "");
device_printf(dev, " card: %s\n", ivar->card_id_string); device_printf(dev, " card: %s\n", ivar->card_id_string);
device_printf(dev, " bus: %ubit, %uMHz%s\n", device_printf(dev, " bus: %ubit, %uMHz%s\n",
@ -1237,7 +1299,9 @@ mmc_discover_cards(struct mmc_softc *sc)
if (bootverbose || mmc_debug) if (bootverbose || mmc_debug)
device_printf(sc->dev, "Probing cards\n"); device_printf(sc->dev, "Probing cards\n");
while (1) { while (1) {
sc->squelched++; /* Errors are expected, squelch reporting. */
err = mmc_all_send_cid(sc, raw_cid); err = mmc_all_send_cid(sc, raw_cid);
sc->squelched--;
if (err == MMC_ERR_TIMEOUT) if (err == MMC_ERR_TIMEOUT)
break; break;
if (err != MMC_ERR_NONE) { if (err != MMC_ERR_NONE) {
@ -1263,8 +1327,6 @@ mmc_discover_cards(struct mmc_softc *sc)
if (newcard) { if (newcard) {
ivar = malloc(sizeof(struct mmc_ivars), M_DEVBUF, ivar = malloc(sizeof(struct mmc_ivars), M_DEVBUF,
M_WAITOK | M_ZERO); M_WAITOK | M_ZERO);
if (!ivar)
return;
memcpy(ivar->raw_cid, raw_cid, sizeof(raw_cid)); memcpy(ivar->raw_cid, raw_cid, sizeof(raw_cid));
} }
if (mmcbr_get_ro(sc->dev)) if (mmcbr_get_ro(sc->dev))
@ -1319,6 +1381,21 @@ mmc_discover_cards(struct mmc_softc *sc)
ivar->hs_tran_speed = SD_MAX_HS; ivar->hs_tran_speed = SD_MAX_HS;
} }
} }
/*
* We deselect then reselect the card here. Some cards
* become unselected and timeout with the above two
* commands, although the state tables / diagrams in the
* standard suggest they go back to the transfer state.
* Other cards don't become deselected, and if we
* atttempt to blindly re-select them, we get timeout
* errors from some controllers. So we deselect then
* reselect to handle all situations. The only thing we
* use from the sd_status is the erase sector size, but
* it is still nice to get that right.
*/
mmc_select_card(sc, 0);
mmc_select_card(sc, ivar->rca);
mmc_app_sd_status(sc, ivar->rca, ivar->raw_sd_status); mmc_app_sd_status(sc, ivar->rca, ivar->raw_sd_status);
mmc_app_decode_sd_status(ivar->raw_sd_status, mmc_app_decode_sd_status(ivar->raw_sd_status,
&ivar->sd_status); &ivar->sd_status);
@ -1326,7 +1403,6 @@ mmc_discover_cards(struct mmc_softc *sc)
ivar->erase_sector = ivar->erase_sector =
16 << ivar->sd_status.au_size; 16 << ivar->sd_status.au_size;
} }
mmc_select_card(sc, 0);
/* Find max supported bus width. */ /* Find max supported bus width. */
if ((mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) && if ((mmcbr_get_caps(sc->dev) & MMC_CAP_4_BIT_DATA) &&
(ivar->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) (ivar->scr.bus_widths & SD_SCR_BUS_WIDTH_4))
@ -1354,6 +1430,7 @@ mmc_discover_cards(struct mmc_softc *sc)
child = device_add_child(sc->dev, NULL, -1); child = device_add_child(sc->dev, NULL, -1);
device_set_ivars(child, ivar); device_set_ivars(child, ivar);
} }
mmc_select_card(sc, 0);
return; return;
} }
mmc_decode_cid_mmc(ivar->raw_cid, &ivar->cid); mmc_decode_cid_mmc(ivar->raw_cid, &ivar->cid);
@ -1386,10 +1463,10 @@ mmc_discover_cards(struct mmc_softc *sc)
break; break;
} }
mmc_select_card(sc, ivar->rca);
/* Only MMC >= 4.x cards support EXT_CSD. */ /* Only MMC >= 4.x cards support EXT_CSD. */
if (ivar->csd.spec_vers >= 4) { if (ivar->csd.spec_vers >= 4) {
/* Card must be selected to fetch EXT_CSD. */
mmc_select_card(sc, ivar->rca);
mmc_send_ext_csd(sc, ivar->raw_ext_csd); mmc_send_ext_csd(sc, ivar->raw_ext_csd);
/* Handle extended capacity from EXT_CSD */ /* Handle extended capacity from EXT_CSD */
sec_count = ivar->raw_ext_csd[EXT_CSD_SEC_CNT] + sec_count = ivar->raw_ext_csd[EXT_CSD_SEC_CNT] +
@ -1412,7 +1489,6 @@ mmc_discover_cards(struct mmc_softc *sc)
ivar->hs_tran_speed = ivar->tran_speed; ivar->hs_tran_speed = ivar->tran_speed;
/* Find max supported bus width. */ /* Find max supported bus width. */
ivar->bus_width = mmc_test_bus_width(sc); ivar->bus_width = mmc_test_bus_width(sc);
mmc_select_card(sc, 0);
/* Handle HC erase sector size. */ /* Handle HC erase sector size. */
if (ivar->raw_ext_csd[EXT_CSD_ERASE_GRP_SIZE] != 0) { if (ivar->raw_ext_csd[EXT_CSD_ERASE_GRP_SIZE] != 0) {
ivar->erase_sector = 1024 * ivar->erase_sector = 1024 *
@ -1446,6 +1522,7 @@ mmc_discover_cards(struct mmc_softc *sc)
child = device_add_child(sc->dev, NULL, -1); child = device_add_child(sc->dev, NULL, -1);
device_set_ivars(child, ivar); device_set_ivars(child, ivar);
} }
mmc_select_card(sc, 0);
} }
} }
@ -1505,6 +1582,7 @@ mmc_go_discovery(struct mmc_softc *sc)
/* /*
* First, try SD modes * First, try SD modes
*/ */
sc->squelched++; /* Errors are expected, squelch reporting. */
mmcbr_set_mode(dev, mode_sd); mmcbr_set_mode(dev, mode_sd);
mmc_power_up(sc); mmc_power_up(sc);
mmcbr_set_bus_mode(dev, pushpull); mmcbr_set_bus_mode(dev, pushpull);
@ -1530,13 +1608,14 @@ mmc_go_discovery(struct mmc_softc *sc)
"MMC probe: OK (OCR: 0x%08x)\n", ocr); "MMC probe: OK (OCR: 0x%08x)\n", ocr);
} else if (bootverbose || mmc_debug) } else if (bootverbose || mmc_debug)
device_printf(sc->dev, "SD probe: OK (OCR: 0x%08x)\n", ocr); device_printf(sc->dev, "SD probe: OK (OCR: 0x%08x)\n", ocr);
sc->squelched--;
mmcbr_set_ocr(dev, mmc_select_vdd(sc, ocr)); mmcbr_set_ocr(dev, mmc_select_vdd(sc, ocr));
if (mmcbr_get_ocr(dev) != 0) if (mmcbr_get_ocr(dev) != 0)
mmc_idle_cards(sc); mmc_idle_cards(sc);
} else { } else {
mmcbr_set_bus_mode(dev, opendrain); mmcbr_set_bus_mode(dev, opendrain);
mmcbr_set_clock(dev, mmcbr_get_f_min(dev)); mmcbr_set_clock(dev, CARD_ID_FREQUENCY);
mmcbr_update_ios(dev); mmcbr_update_ios(dev);
/* XXX recompute vdd based on new cards? */ /* XXX recompute vdd based on new cards? */
} }
@ -1547,6 +1626,7 @@ mmc_go_discovery(struct mmc_softc *sc)
if (bootverbose || mmc_debug) if (bootverbose || mmc_debug)
device_printf(sc->dev, "Current OCR: 0x%08x\n", mmcbr_get_ocr(dev)); device_printf(sc->dev, "Current OCR: 0x%08x\n", mmcbr_get_ocr(dev));
if (mmcbr_get_ocr(dev) == 0) { if (mmcbr_get_ocr(dev) == 0) {
device_printf(sc->dev, "No compatible cards found on bus\n");
mmc_delete_cards(sc); mmc_delete_cards(sc);
mmc_power_down(sc); mmc_power_down(sc);
return; return;
@ -1559,7 +1639,7 @@ mmc_go_discovery(struct mmc_softc *sc)
mmc_send_app_op_cond(sc, mmc_send_app_op_cond(sc,
(err ? 0 : MMC_OCR_CCS) | mmcbr_get_ocr(dev), NULL); (err ? 0 : MMC_OCR_CCS) | mmcbr_get_ocr(dev), NULL);
} else } else
mmc_send_op_cond(sc, mmcbr_get_ocr(dev), NULL); mmc_send_op_cond(sc, MMC_OCR_CCS | mmcbr_get_ocr(dev), NULL);
mmc_discover_cards(sc); mmc_discover_cards(sc);
mmc_rescan_cards(sc); mmc_rescan_cards(sc);
@ -1574,11 +1654,10 @@ static int
mmc_calculate_clock(struct mmc_softc *sc) mmc_calculate_clock(struct mmc_softc *sc)
{ {
int max_dtr, max_hs_dtr, max_timing; int max_dtr, max_hs_dtr, max_timing;
int nkid, i, f_min, f_max; int nkid, i, f_max;
device_t *kids; device_t *kids;
struct mmc_ivars *ivar; struct mmc_ivars *ivar;
f_min = mmcbr_get_f_min(sc->dev);
f_max = mmcbr_get_f_max(sc->dev); f_max = mmcbr_get_f_max(sc->dev);
max_dtr = max_hs_dtr = f_max; max_dtr = max_hs_dtr = f_max;
if ((mmcbr_get_caps(sc->dev) & MMC_CAP_HSPEED)) if ((mmcbr_get_caps(sc->dev) & MMC_CAP_HSPEED))
@ -1673,6 +1752,9 @@ mmc_read_ivar(device_t bus, device_t child, int which, uintptr_t *result)
case MMC_IVAR_CARD_ID_STRING: case MMC_IVAR_CARD_ID_STRING:
*(char **)result = ivar->card_id_string; *(char **)result = ivar->card_id_string;
break; break;
case MMC_IVAR_CARD_SN_STRING:
*(char **)result = ivar->card_sn_string;
break;
} }
return (0); return (0);
} }
@ -1725,13 +1807,11 @@ static device_method_t mmc_methods[] = {
DEVMETHOD_END DEVMETHOD_END
}; };
static driver_t mmc_driver = { driver_t mmc_driver = {
"mmc", "mmc",
mmc_methods, mmc_methods,
sizeof(struct mmc_softc), sizeof(struct mmc_softc),
}; };
static devclass_t mmc_devclass; devclass_t mmc_devclass;
DRIVER_MODULE(mmc, at91_mci, mmc_driver, mmc_devclass, NULL, NULL); MODULE_VERSION(mmc, 1);
DRIVER_MODULE(mmc, dw_mmc, mmc_driver, mmc_devclass, NULL, NULL);
DRIVER_MODULE(mmc, sdhci, mmc_driver, mmc_devclass, NULL, NULL);

View File

@ -85,8 +85,11 @@ struct mmc_command {
#define MMC_RSP_R1B (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | MMC_RSP_BUSY) #define MMC_RSP_R1B (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | MMC_RSP_BUSY)
#define MMC_RSP_R2 (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC) #define MMC_RSP_R2 (MMC_RSP_PRESENT | MMC_RSP_136 | MMC_RSP_CRC)
#define MMC_RSP_R3 (MMC_RSP_PRESENT) #define MMC_RSP_R3 (MMC_RSP_PRESENT)
#define MMC_RSP_R6 (MMC_RSP_PRESENT | MMC_RSP_CRC) #define MMC_RSP_R4 (MMC_RSP_PRESENT)
#define MMC_RSP_R7 (MMC_RSP_PRESENT | MMC_RSP_CRC) #define MMC_RSP_R5 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
#define MMC_RSP_R5B (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE | MMC_RSP_BUSY)
#define MMC_RSP_R6 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
#define MMC_RSP_R7 (MMC_RSP_PRESENT | MMC_RSP_CRC | MMC_RSP_OPCODE)
#define MMC_RSP(x) ((x) & MMC_RSP_MASK) #define MMC_RSP(x) ((x) & MMC_RSP_MASK)
uint32_t retries; uint32_t retries;
uint32_t error; uint32_t error;
@ -353,6 +356,7 @@ struct mmc_request {
#define MMC_OCR_VOLTAGE 0x3fffffffU /* Vdd Voltage mask */ #define MMC_OCR_VOLTAGE 0x3fffffffU /* Vdd Voltage mask */
#define MMC_OCR_LOW_VOLTAGE (1u << 7) /* Low Voltage Range -- tbd */ #define MMC_OCR_LOW_VOLTAGE (1u << 7) /* Low Voltage Range -- tbd */
#define MMC_OCR_200_210 (1U << 8) /* Vdd voltage 2.00 ~ 2.10 */ #define MMC_OCR_200_210 (1U << 8) /* Vdd voltage 2.00 ~ 2.10 */
#define MMC_OCR_MIN_VOLTAGE_SHIFT 8
#define MMC_OCR_210_220 (1U << 9) /* Vdd voltage 2.10 ~ 2.20 */ #define MMC_OCR_210_220 (1U << 9) /* Vdd voltage 2.10 ~ 2.20 */
#define MMC_OCR_220_230 (1U << 10) /* Vdd voltage 2.20 ~ 2.30 */ #define MMC_OCR_220_230 (1U << 10) /* Vdd voltage 2.20 ~ 2.30 */
#define MMC_OCR_230_240 (1U << 11) /* Vdd voltage 2.30 ~ 2.40 */ #define MMC_OCR_230_240 (1U << 11) /* Vdd voltage 2.30 ~ 2.40 */
@ -368,6 +372,7 @@ struct mmc_request {
#define MMC_OCR_330_340 (1U << 21) /* Vdd voltage 3.30 ~ 3.40 */ #define MMC_OCR_330_340 (1U << 21) /* Vdd voltage 3.30 ~ 3.40 */
#define MMC_OCR_340_350 (1U << 22) /* Vdd voltage 3.40 ~ 3.50 */ #define MMC_OCR_340_350 (1U << 22) /* Vdd voltage 3.40 ~ 3.50 */
#define MMC_OCR_350_360 (1U << 23) /* Vdd voltage 3.50 ~ 3.60 */ #define MMC_OCR_350_360 (1U << 23) /* Vdd voltage 3.50 ~ 3.60 */
#define MMC_OCR_MAX_VOLTAGE_SHIFT 23
#define MMC_OCR_CCS (1u << 30) /* Card Capacity status (SD vs SDHC) */ #define MMC_OCR_CCS (1u << 30) /* Card Capacity status (SD vs SDHC) */
#define MMC_OCR_CARD_BUSY (1U << 31) /* Card Power up status */ #define MMC_OCR_CARD_BUSY (1U << 31) /* Card Power up status */
@ -436,7 +441,7 @@ struct mmc_sd_status
* Older versions of the MMC standard had a variable sector size. However, * Older versions of the MMC standard had a variable sector size. However,
* I've been able to find no old MMC or SD cards that have a non 512 * I've been able to find no old MMC or SD cards that have a non 512
* byte sector size anywhere, so we assume that such cards are very rare * byte sector size anywhere, so we assume that such cards are very rare
* and only note their existance in passing here... * and only note their existence in passing here...
*/ */
#define MMC_SECTOR_SIZE 512 #define MMC_SECTOR_SIZE 512

View File

@ -66,6 +66,8 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/module.h> #include <sys/module.h>
#include <sys/mutex.h> #include <sys/mutex.h>
#include <sys/time.h>
#include <geom/geom.h>
#include <geom/geom_disk.h> #include <geom/geom_disk.h>
#include <dev/mmc/mmcbrvar.h> #include <dev/mmc/mmcbrvar.h>
@ -96,9 +98,26 @@ struct mmcsd_softc {
daddr_t eblock, eend; /* Range remaining after the last erase. */ daddr_t eblock, eend; /* Range remaining after the last erase. */
int running; int running;
int suspend; int suspend;
int log_count;
struct timeval log_time;
#endif /* __rtems__ */ #endif /* __rtems__ */
}; };
#ifndef __rtems__
static const char *errmsg[] =
{
"None",
"Timeout",
"Bad CRC",
"Fifo",
"Failed",
"Invalid",
"NO MEMORY"
};
#endif /* __rtems__ */
#define LOG_PPS 5 /* Log no more than 5 errors per second. */
/* bus entry points */ /* bus entry points */
static int mmcsd_attach(device_t dev); static int mmcsd_attach(device_t dev);
static int mmcsd_detach(device_t dev); static int mmcsd_detach(device_t dev);
@ -347,6 +366,11 @@ mmcsd_attach(device_t dev)
struct mmcsd_softc *sc; struct mmcsd_softc *sc;
#ifndef __rtems__ #ifndef __rtems__
struct disk *d; struct disk *d;
#else /* __rtems__ */
struct {
char d_ident[16];
char d_descr[64];
} x, *d = &x;
#endif /* __rtems__ */ #endif /* __rtems__ */
intmax_t mb; intmax_t mb;
uint32_t speed; uint32_t speed;
@ -365,45 +389,49 @@ mmcsd_attach(device_t dev)
d->d_dump = mmcsd_dump; d->d_dump = mmcsd_dump;
d->d_name = "mmcsd"; d->d_name = "mmcsd";
d->d_drv1 = sc; d->d_drv1 = sc;
d->d_maxsize = 4*1024*1024; /* Maximum defined SD card AU size. */
d->d_sectorsize = mmc_get_sector_size(dev); d->d_sectorsize = mmc_get_sector_size(dev);
d->d_maxsize = mmc_get_max_data(dev) * d->d_sectorsize;
d->d_mediasize = (off_t)mmc_get_media_size(dev) * d->d_sectorsize; d->d_mediasize = (off_t)mmc_get_media_size(dev) * d->d_sectorsize;
d->d_stripeoffset = 0;
d->d_stripesize = mmc_get_erase_sector(dev) * d->d_sectorsize; d->d_stripesize = mmc_get_erase_sector(dev) * d->d_sectorsize;
d->d_unit = device_get_unit(dev); d->d_unit = device_get_unit(dev);
d->d_flags = DISKFLAG_CANDELETE; d->d_flags = DISKFLAG_CANDELETE;
d->d_delmaxsize = mmc_get_erase_sector(dev) * d->d_sectorsize;
#endif /* __rtems__ */
strlcpy(d->d_ident, mmc_get_card_sn_string(dev), sizeof(d->d_ident));
strlcpy(d->d_descr, mmc_get_card_id_string(dev), sizeof(d->d_descr));
#ifndef __rtems__
/* /*
* Display in most natural units. There's no cards < 1MB. * Display in most natural units. There's no cards < 1MB. The SD
* The SD standard goes to 2GiB, but the data format supports * standard goes to 2GiB due to its reliance on FAT, but the data
* up to 4GiB and some card makers push it up to this limit. * format supports up to 4GiB and some card makers push it up to this
* The SDHC standard only goes to 32GiB (the data format in * limit. The SDHC standard only goes to 32GiB due to FAT32, but the
* SDHC is good to 2TiB however, which isn't too ugly at * data format supports up to 2TiB however. 2048GB isn't too ugly, so
* 2048GiBm, so we note it in passing here and don't add the * we note it in passing here and don't add the code to print
* code to print TiB). * TB). Since these cards are sold in terms of MB and GB not MiB and
* GiB, report them like that. We also round to the nearest unit, since
* many cards are a few percent short, even of the power of 10 size.
*/ */
mb = d->d_mediasize >> 20; /* 1MiB == 1 << 20 */ mb = (d->d_mediasize + 1000000 / 2 - 1) / 1000000;
#else /* __rtems__ */ #else /* __rtems__ */
mb = mmc_get_media_size(dev); mb = mmc_get_media_size(dev);
mb *= mmc_get_sector_size(dev); mb *= mmc_get_sector_size(dev);
mb >>= 20; mb = (mb + 1000000 / 2 - 1) / 1000000;
#endif /* __rtems__ */ #endif /* __rtems__ */
unit = 'M'; unit = 'M';
if (mb >= 10240) { /* 1GiB = 1024 MiB */ if (mb >= 1000) {
unit = 'G'; unit = 'G';
mb /= 1024; mb = (mb + 1000 / 2 - 1) / 1000;
} }
/* /*
* Report the clock speed of the underlying hardware, which might be * Report the clock speed of the underlying hardware, which might be
* different than what the card reports due to hardware limitations. * different than what the card reports due to hardware limitations.
* Report how many blocks the hardware transfers at once, but clip the * Report how many blocks the hardware transfers at once.
* number to MAXPHYS since the system won't initiate larger transfers.
*/ */
speed = mmcbr_get_clock(device_get_parent(dev)); speed = mmcbr_get_clock(device_get_parent(dev));
maxblocks = mmc_get_max_data(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", device_printf(dev, "%ju%cB <%s>%s at %s %d.%01dMHz/%dbit/%d-block\n",
mb, unit, mmc_get_card_id_string(dev), mb, unit, d->d_descr,
mmc_get_read_only(dev) ? " (read-only)" : "", mmc_get_read_only(dev) ? " (read-only)" : "",
device_get_nameunit(device_get_parent(dev)), device_get_nameunit(device_get_parent(dev)),
speed / 1000000, (speed / 100000) % 10, speed / 1000000, (speed / 100000) % 10,
@ -415,7 +443,8 @@ mmcsd_attach(device_t dev)
sc->running = 1; sc->running = 1;
sc->suspend = 0; sc->suspend = 0;
sc->eblock = sc->eend = 0; sc->eblock = sc->eend = 0;
kproc_create(&mmcsd_task, sc, &sc->p, 0, 0, "task: mmc/sd card"); kproc_create(&mmcsd_task, sc, &sc->p, 0, 0, "%s: mmc/sd card",
device_get_nameunit(dev));
#else /* __rtems__ */ #else /* __rtems__ */
rtems_status_code status_code = rtems_media_server_disk_attach( rtems_status_code status_code = rtems_media_server_disk_attach(
device_get_name(dev), device_get_name(dev),
@ -493,7 +522,8 @@ mmcsd_resume(device_t dev)
if (sc->running <= 0) { if (sc->running <= 0) {
sc->running = 1; sc->running = 1;
MMCSD_UNLOCK(sc); MMCSD_UNLOCK(sc);
kproc_create(&mmcsd_task, sc, &sc->p, 0, 0, "task: mmc/sd card"); kproc_create(&mmcsd_task, sc, &sc->p, 0, 0, "%s: mmc/sd card",
device_get_nameunit(dev));
} else } else
MMCSD_UNLOCK(sc); MMCSD_UNLOCK(sc);
#else /* __rtems__ */ #else /* __rtems__ */
@ -534,6 +564,14 @@ mmcsd_strategy(struct bio *bp)
} }
} }
static const char *
mmcsd_errmsg(int e)
{
if (e < 0 || e > MMC_ERR_MAX)
return "Bad error code";
return errmsg[e];
}
static daddr_t static daddr_t
mmcsd_rw(struct mmcsd_softc *sc, struct bio *bp) mmcsd_rw(struct mmcsd_softc *sc, struct bio *bp)
{ {
@ -544,6 +582,7 @@ mmcsd_rw(struct mmcsd_softc *sc, struct bio *bp)
struct mmc_data data; struct mmc_data data;
device_t dev = sc->dev; device_t dev = sc->dev;
int sz = sc->disk->d_sectorsize; int sz = sc->disk->d_sectorsize;
device_t mmcbr = device_get_parent(dev);
block = bp->bio_pblkno; block = bp->bio_pblkno;
end = bp->bio_pblkno + (bp->bio_bcount / sz); end = bp->bio_pblkno + (bp->bio_bcount / sz);
@ -554,6 +593,8 @@ mmcsd_rw(struct mmcsd_softc *sc, struct bio *bp)
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
memset(&stop, 0, sizeof(stop)); memset(&stop, 0, sizeof(stop));
memset(&data, 0, sizeof(data));
cmd.mrq = &req;
req.cmd = &cmd; req.cmd = &cmd;
cmd.data = &data; cmd.data = &data;
if (bp->bio_cmd == BIO_READ) { if (bp->bio_cmd == BIO_READ) {
@ -583,14 +624,17 @@ mmcsd_rw(struct mmcsd_softc *sc, struct bio *bp)
stop.opcode = MMC_STOP_TRANSMISSION; stop.opcode = MMC_STOP_TRANSMISSION;
stop.arg = 0; stop.arg = 0;
stop.flags = MMC_RSP_R1B | MMC_CMD_AC; stop.flags = MMC_RSP_R1B | MMC_CMD_AC;
stop.mrq = &req;
req.stop = &stop; req.stop = &stop;
} }
// printf("Len %d %lld-%lld flags %#x sz %d\n", MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
// (int)data.len, (long long)block, (long long)end, data.flags, sz); if (req.cmd->error != MMC_ERR_NONE) {
MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev, if (ppsratecheck(&sc->log_time, &sc->log_count, LOG_PPS)) {
&req); device_printf(dev, "Error indicated: %d %s\n",
if (req.cmd->error != MMC_ERR_NONE) req.cmd->error, mmcsd_errmsg(req.cmd->error));
}
break; break;
}
block += numblocks; block += numblocks;
} }
return (block); return (block);
@ -605,6 +649,7 @@ mmcsd_delete(struct mmcsd_softc *sc, struct bio *bp)
device_t dev = sc->dev; device_t dev = sc->dev;
int sz = sc->disk->d_sectorsize; int sz = sc->disk->d_sectorsize;
int erase_sector; int erase_sector;
device_t mmcbr = device_get_parent(dev);
block = bp->bio_pblkno; block = bp->bio_pblkno;
end = bp->bio_pblkno + (bp->bio_bcount / sz); end = bp->bio_pblkno + (bp->bio_bcount / sz);
@ -629,6 +674,7 @@ mmcsd_delete(struct mmcsd_softc *sc, struct bio *bp)
/* Set erase start position. */ /* Set erase start position. */
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
memset(&cmd, 0, sizeof(cmd)); memset(&cmd, 0, sizeof(cmd));
cmd.mrq = &req;
req.cmd = &cmd; req.cmd = &cmd;
if (mmc_get_card_type(dev) == mode_sd) if (mmc_get_card_type(dev) == mode_sd)
cmd.opcode = SD_ERASE_WR_BLK_START; cmd.opcode = SD_ERASE_WR_BLK_START;
@ -638,8 +684,7 @@ mmcsd_delete(struct mmcsd_softc *sc, struct bio *bp)
if (!mmc_get_high_cap(dev)) if (!mmc_get_high_cap(dev))
cmd.arg <<= 9; cmd.arg <<= 9;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev, MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
&req);
if (req.cmd->error != MMC_ERR_NONE) { if (req.cmd->error != MMC_ERR_NONE) {
printf("erase err1: %d\n", req.cmd->error); printf("erase err1: %d\n", req.cmd->error);
return (block); return (block);
@ -657,8 +702,7 @@ mmcsd_delete(struct mmcsd_softc *sc, struct bio *bp)
cmd.arg <<= 9; cmd.arg <<= 9;
cmd.arg--; cmd.arg--;
cmd.flags = MMC_RSP_R1 | MMC_CMD_AC; cmd.flags = MMC_RSP_R1 | MMC_CMD_AC;
MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev, MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
&req);
if (req.cmd->error != MMC_ERR_NONE) { if (req.cmd->error != MMC_ERR_NONE) {
printf("erase err2: %d\n", req.cmd->error); printf("erase err2: %d\n", req.cmd->error);
return (block); return (block);
@ -670,8 +714,7 @@ mmcsd_delete(struct mmcsd_softc *sc, struct bio *bp)
cmd.opcode = MMC_ERASE; cmd.opcode = MMC_ERASE;
cmd.arg = 0; cmd.arg = 0;
cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; cmd.flags = MMC_RSP_R1B | MMC_CMD_AC;
MMCBUS_WAIT_FOR_REQUEST(device_get_parent(dev), dev, MMCBUS_WAIT_FOR_REQUEST(mmcbr, dev, &req);
&req);
if (req.cmd->error != MMC_ERR_NONE) { if (req.cmd->error != MMC_ERR_NONE) {
printf("erase err3 %d\n", req.cmd->error); printf("erase err3 %d\n", req.cmd->error);
return (block); return (block);
@ -696,21 +739,22 @@ mmcsd_dump(void *arg, void *virtual, vm_offset_t physical,
device_t dev = sc->dev; device_t dev = sc->dev;
struct bio bp; struct bio bp;
daddr_t block, end; daddr_t block, end;
device_t mmcbr = device_get_parent(dev);
/* length zero is special and really means flush buffers to media */ /* length zero is special and really means flush buffers to media */
if (!length) if (!length)
return (0); return (0);
bzero(&bp, sizeof(struct bio)); g_reset_bio(&bp);
bp.bio_disk = disk; bp.bio_disk = disk;
bp.bio_pblkno = offset / disk->d_sectorsize; bp.bio_pblkno = offset / disk->d_sectorsize;
bp.bio_bcount = length; bp.bio_bcount = length;
bp.bio_data = virtual; bp.bio_data = virtual;
bp.bio_cmd = BIO_WRITE; bp.bio_cmd = BIO_WRITE;
end = bp.bio_pblkno + bp.bio_bcount / sc->disk->d_sectorsize; end = bp.bio_pblkno + bp.bio_bcount / sc->disk->d_sectorsize;
MMCBUS_ACQUIRE_BUS(device_get_parent(dev), dev); MMCBUS_ACQUIRE_BUS(mmcbr, dev);
block = mmcsd_rw(sc, &bp); block = mmcsd_rw(sc, &bp);
MMCBUS_RELEASE_BUS(device_get_parent(dev), dev); MMCBUS_RELEASE_BUS(mmcbr, dev);
return ((end < block) ? EIO : 0); return ((end < block) ? EIO : 0);
} }
@ -721,9 +765,9 @@ mmcsd_task(void *arg)
struct bio *bp; struct bio *bp;
int sz; int sz;
daddr_t block, end; daddr_t block, end;
device_t dev; device_t dev = sc->dev;
device_t mmcbr = device_get_parent(sc->dev);
dev = sc->dev;
while (1) { while (1) {
MMCSD_LOCK(sc); MMCSD_LOCK(sc);
do { do {
@ -741,7 +785,7 @@ mmcsd_task(void *arg)
biodone(bp); biodone(bp);
continue; continue;
} }
MMCBUS_ACQUIRE_BUS(device_get_parent(dev), dev); MMCBUS_ACQUIRE_BUS(mmcbr, dev);
sz = sc->disk->d_sectorsize; sz = sc->disk->d_sectorsize;
block = bp->bio_pblkno; block = bp->bio_pblkno;
end = bp->bio_pblkno + (bp->bio_bcount / sz); end = bp->bio_pblkno + (bp->bio_bcount / sz);
@ -753,7 +797,7 @@ mmcsd_task(void *arg)
} else if (bp->bio_cmd == BIO_DELETE) { } else if (bp->bio_cmd == BIO_DELETE) {
block = mmcsd_delete(sc, bp); block = mmcsd_delete(sc, bp);
} }
MMCBUS_RELEASE_BUS(device_get_parent(dev), dev); MMCBUS_RELEASE_BUS(mmcbr, dev);
if (block < end) { if (block < end) {
bp->bio_error = EIO; bp->bio_error = EIO;
bp->bio_resid = (end - block) * sz; bp->bio_resid = (end - block) * sz;

View File

@ -69,25 +69,18 @@ enum mmc_device_ivars {
MMC_IVAR_BUS_WIDTH, MMC_IVAR_BUS_WIDTH,
MMC_IVAR_ERASE_SECTOR, MMC_IVAR_ERASE_SECTOR,
MMC_IVAR_MAX_DATA, MMC_IVAR_MAX_DATA,
MMC_IVAR_CARD_ID_STRING MMC_IVAR_CARD_ID_STRING,
MMC_IVAR_CARD_SN_STRING,
}; };
/* /*
* Simplified accessors for pci devices * Simplified accessors for mmc devices
*/ */
#define MMC_ACCESSOR(var, ivar, type) \ #define MMC_ACCESSOR(var, ivar, type) \
__BUS_ACCESSOR(mmc, var, MMC, ivar, type) __BUS_ACCESSOR(mmc, var, MMC, ivar, type)
MMC_ACCESSOR(dsr_imp, DSR_IMP, int) MMC_ACCESSOR(dsr_imp, DSR_IMP, int)
#ifndef __rtems__ MMC_ACCESSOR(media_size, MEDIA_SIZE, long)
MMC_ACCESSOR(media_size, MEDIA_SIZE, off_t)
#else /* __rtems__ */
/*
* The instance variable value storage is limited by the uintptr_t type. Since
* off_t has more bits than uintptr_t on most RTEMS targets, we need this hack.
*/
MMC_ACCESSOR(media_size, MEDIA_SIZE, uintptr_t)
#endif /* __rtems__ */
MMC_ACCESSOR(rca, RCA, int) MMC_ACCESSOR(rca, RCA, int)
MMC_ACCESSOR(sector_size, SECTOR_SIZE, int) MMC_ACCESSOR(sector_size, SECTOR_SIZE, int)
MMC_ACCESSOR(tran_speed, TRAN_SPEED, int) MMC_ACCESSOR(tran_speed, TRAN_SPEED, int)
@ -98,5 +91,6 @@ MMC_ACCESSOR(bus_width, BUS_WIDTH, int)
MMC_ACCESSOR(erase_sector, ERASE_SECTOR, int) MMC_ACCESSOR(erase_sector, ERASE_SECTOR, int)
MMC_ACCESSOR(max_data, MAX_DATA, int) MMC_ACCESSOR(max_data, MAX_DATA, int)
MMC_ACCESSOR(card_id_string, CARD_ID_STRING, const char *) MMC_ACCESSOR(card_id_string, CARD_ID_STRING, const char *)
MMC_ACCESSOR(card_sn_string, CARD_SN_STRING, const char *)
#endif /* DEV_MMC_MMCVAR_H */ #endif /* DEV_MMC_MMCVAR_H */

View File

@ -766,6 +766,7 @@ detail and debug level information from the command.
== FreeBSD version of imported files and directories == FreeBSD version of imported files and directories
. sys/dev/dwc/*, trunk, 2015-03-26, cfc3df2b8f708ce8494d9d556e3472a5c8c21b8a . sys/dev/dwc/*, trunk, 2015-03-26, cfc3df2b8f708ce8494d9d556e3472a5c8c21b8a
. sys/dev/mmc/*, trunk, 2016-08-23, 9fe7c416e6abb28b1398fd3e5687099846800cfd
. sys/dev/usb/*, trunk, 2015-10-30, 968dafb4fcf133cb8beb6fa3c558fecd7dc00ef0 . sys/dev/usb/*, trunk, 2015-10-30, 968dafb4fcf133cb8beb6fa3c558fecd7dc00ef0
. *, stable/9, 2015-04-08, 99a648a912e81e29d9c4c159cbbe263462f2d719 . *, stable/9, 2015-04-08, 99a648a912e81e29d9c4c159cbbe263462f2d719

View File