#include <linux/delay.h>
#include <linux/pagemap.h>
#include <linux/err.h>
+#include <linux/leds.h>
#include <asm/scatterlist.h>
#include <linux/scatterlist.h>
static struct workqueue_struct *workqueue;
+/*
+ * Enabling software CRCs on the data blocks can be a significant (30%)
+ * performance cost, and for other reasons may not always be desired.
+ * So we allow it it to be disabled.
+ */
+int use_spi_crc = 1;
+module_param(use_spi_crc, bool, 0);
+
/*
* Internal function. Schedule delayed work in the MMC work queue.
*/
struct mmc_command *cmd = mrq->cmd;
int err = cmd->error;
+ if (err && cmd->retries && mmc_host_is_spi(host)) {
+ if (cmd->resp[0] & R1_SPI_ILLEGAL_COMMAND)
+ cmd->retries = 0;
+ }
+
if (err && cmd->retries) {
pr_debug("%s: req failed (CMD%u): %d, retrying...\n",
mmc_hostname(host), cmd->opcode, err);
cmd->error = 0;
host->ops->request(host, mrq);
} else {
+ led_trigger_event(host->led, LED_OFF);
+
pr_debug("%s: req done (CMD%u): %d: %08x %08x %08x %08x\n",
mmc_hostname(host), cmd->opcode, err,
cmd->resp[0], cmd->resp[1],
WARN_ON(!host->claimed);
+ led_trigger_event(host->led, LED_FULL);
+
mrq->cmd->error = 0;
mrq->cmd->mrq = mrq;
if (mrq->data) {
int bit = fls(host->ocr_avail) - 1;
host->ios.vdd = bit;
- host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
- host->ios.chip_select = MMC_CS_DONTCARE;
+ if (mmc_host_is_spi(host)) {
+ host->ios.chip_select = MMC_CS_HIGH;
+ host->ios.bus_mode = MMC_BUSMODE_PUSHPULL;
+ } else {
+ host->ios.chip_select = MMC_CS_DONTCARE;
+ host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+ }
host->ios.power_mode = MMC_POWER_UP;
host->ios.bus_width = MMC_BUS_WIDTH_1;
host->ios.timing = MMC_TIMING_LEGACY;
mmc_set_ios(host);
- mmc_delay(1);
+ /*
+ * This delay should be sufficient to allow the power supply
+ * to reach the minimum voltage.
+ */
+ mmc_delay(2);
host->ios.clock = host->f_min;
host->ios.power_mode = MMC_POWER_ON;
mmc_set_ios(host);
+ /*
+ * This delay must be at least 74 clock sizes, or 1 ms, or the
+ * time required to reach a stable voltage.
+ */
mmc_delay(2);
}
{
host->ios.clock = 0;
host->ios.vdd = 0;
- host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
- host->ios.chip_select = MMC_CS_DONTCARE;
+ if (!mmc_host_is_spi(host)) {
+ host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
+ host->ios.chip_select = MMC_CS_DONTCARE;
+ }
host->ios.power_mode = MMC_POWER_OFF;
host->ios.bus_width = MMC_BUS_WIDTH_1;
host->ios.timing = MMC_TIMING_LEGACY;