mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-05-14 04:29:18 +08:00
mmc: Update to FreeBSD trunk 2016-08-23
This commit is contained in:
parent
a971614a91
commit
0c24e06130
@ -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 */
|
||||||
|
@ -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);
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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 */
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
0
rtemsbsd/include/geom/geom.h
Normal file
0
rtemsbsd/include/geom/geom.h
Normal file
Loading…
x
Reference in New Issue
Block a user