On Sat, 14 Jul 2007 15:08:06 -0700
David Brownell <[EMAIL PROTECTED]> wrote:

> --- g26.orig/drivers/mmc/host/Kconfig 2007-07-14 14:47:11.000000000 -0700
> +++ g26/drivers/mmc/host/Kconfig      2007-07-14 14:47:57.000000000 -0700
> @@ -100,3 +100,16 @@ config MMC_TIFM_SD
>            To compile this driver as a module, choose M here: the
>         module will be called tifm_sd.
>  
> +config MMC_SPI
> +     tristate "MMC/SD over SPI"
> +     depends on MMC && SPI_MASTER && !HIGHMEM && EXPERIMENTAL
> +     select CRC7
> +     select CRC_ITU_T
> +     help
> +       Some systems accss MMC/SD cards using a SPI controller instead of
> +       using a "native" MMC/SD controller.  This has a disadvantage of
> +       being relatively high overhead, but a compensating advantage of
> +       working on many systems without dedicated MMC/SD controllers.
> +
> +       If unsure, or if your system has no SPI master driver, say N.
> +

It is customary to have "(Experimental)" in the description aswell.

> +
> +static int
> +mmc_spi_readbytes(struct mmc_spi_host *host, unsigned len)
> +{
> +     int status;
> +
> +     if (len > sizeof *host->data) {
> +             WARN_ON(1);
> +             return -EIO;
> +     }

sizeof without parenthesis? Heathen!

> +
> +/*
> + * Note that for SPI, cmd->resp[0] is not the same data as "native" protocol
> + * hosts return!  The low byte holds R1_SPI bits.  The next byte may hold
> + * R2_SPI bits ... for SEND_STATUS, or after data read errors.
> + *
> + * cmd->resp[1] holds any four-byte response, for R3 (READ_OCR) and on
> + * newer cards R7 (IF_COND).
> + */
> +
> +static char *maptype(struct mmc_command *cmd)
> +{
> +     switch (mmc_spi_resp_type(cmd)) {
> +     case MMC_RSP_SPI_R1:    return "R1";
> +     case MMC_RSP_SPI_R1B:   return "R1B";
> +     case MMC_RSP_SPI_R2:    return "R2";
> +     case MMC_RSP_SPI_R3:    return "R3/R7";
> +     default:                return "?";
> +     }
> +}
> +

I'm trying to move all generic debugging code into the core, so I would prefer 
if you would have a look at extending that to fit your needs. That way everyone 
wins.

> +
> +     /* Status byte: the entire seven-bit R1 response.  */
> +     if (cmd->resp[0] != 0) {
> +             if (R1_SPI_COM_CRC & cmd->resp[0]) {
> +                     cmd->error = MMC_ERR_BADCRC;
> +                     value = -EILSEQ;
> +             } else if ((R1_SPI_PARAMETER | R1_SPI_ADDRESS
> +                                     | R1_SPI_ILLEGAL_COMMAND)
> +                             & cmd->resp[0]) {
> +                     cmd->error = MMC_ERR_INVALID;
> +                     value = -EINVAL;
> +             } else if ((R1_SPI_ERASE_SEQ | R1_SPI_ERASE_RESET)
> +                             & cmd->resp[0]) {
> +                     cmd->error = MMC_ERR_FAILED;
> +                     value = -EINVAL;
> +             } /* else R1_SPI_IDLE, "it's resetting" */
> +
> +             if (value < 0)
> +                     goto fail;
> +     }

I'd still preferred that you'd didn't try to decode this here. And your code 
demostrates why; CRC error and illegal command both signal problems with the 
previous command, not the current one, so this code would be failing the wrong 
request.

> +
> +     switch (mmc_spi_resp_type(cmd)) {
> +
> +     /* SPI R1B == R1 + busy; STOP_TRANSMISSION (for multiblock reads)
> +      * and less-common stuff like various erase operations.
> +      */
> +     case MMC_RSP_SPI_R1B:

for (i = 0;i < mmc_spi_resp_size(cmd);i++)
        cmd->resp[i/4] |= *cp++ << (24 - (i % 4) * 8);

if (cmd->flags & MMC_SPI_RSP_BUSY)
        mmc_spi_wait_unbusy();

That's the whole point of hacking up the response types into components, so 
that the host driver doesn't have to care.

You can keep your design if you'd like, but I really think this is cleaner and 
more layered.

> +
> +     /* We can handle most commands (except block reads) in one full
> +      * duplex I/O operation before either starting the next transfer
> +      * (data block or command) or else deselecting the card.
> +      *
> +      * First, write 7 bytes:
> +      *  - an all-ones byte to ensure the card is ready
> +      *  - opcode byte (plus start and transmission bits)
> +      *  - four bytes of big-endian argument
> +      *  - crc7 (plus end bit) ... always computed, it's cheap
> +      *

I thought your argument against always using crc7 was that it wasn't cheap? 
Colour me confused.


> +                     if (status == -EILSEQ)
> +                             data->error = MMC_ERR_BADCRC;
> +                     else if (status == -ETIMEDOUT)
> +                             data->error = MMC_ERR_TIMEOUT;
> +                     else if (status == -EINVAL)
> +                             data->error = MMC_ERR_INVALID;
> +                     else if (data->error == MMC_ERR_NONE)
> +                             data->error = MMC_ERR_FAILED;
> +                     break;
> +             }

At least we agree on error codes. This is precisely the change I have pending 
in my patch set to remove the MMC_ERR_* mess. :)


There are a few outstanding issues, but they are really minor so this could 
very soon get into my -mm branch. I need a MAINTAINERS entry aswell.

I'd like to see those REVISIT things attended to before I push the stuff to 
Linus though.

Rgds
-- 
     -- Pierre Ossman

  Linux kernel, MMC maintainer        http://www.kernel.org
  PulseAudio, core developer          http://pulseaudio.org
  rdesktop, core developer          http://www.rdesktop.org

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >>  http://get.splunk.com/
_______________________________________________
spi-devel-general mailing list
spi-devel-general@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/spi-devel-general

Reply via email to