[U-Boot] [PATCH] PIO Mode Read/Write support for FSL eSDHC
Andy Fleming
afleming at gmail.com
Sat Apr 18 00:35:31 CEST 2009
On Fri, Apr 3, 2009 at 11:28 AM, Dipen Dudhat
<dipen.dudhat at freescale.com> wrote:
> PIO mode support for freescale eSDHC Driver.
> PIO has added to enable data transfer without use of eSDHC DMA Engine.
>
> Signed-off-by: Dipen Dudhat <dipen.dudhat at freescale.com>
> ---
> drivers/mmc/fsl_esdhc.c | 136 +++++++++++++++++++++++++++++++++++++++++++----
> include/fsl_esdhc.h | 1 +
> 2 files changed, 127 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/mmc/fsl_esdhc.c b/drivers/mmc/fsl_esdhc.c
> index 0ba45cd..c96011f 100644
> +#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
> +static int esdhc_setup_pio_data(struct mmc *mmc, struct mmc_data *data)
> +{
> + int timeout;
> + struct fsl_esdhc *regs = mmc->priv;
> +
> + if (!(data->flags & MMC_DATA_READ)) {
> + if ((in_be32(®s->prsstat) & PRSSTAT_WPSPL) == 0) {
> + printf("\nThe SD card is locked. "
> + "Can not write to a locked card.\n\n");
> + return TIMEOUT;
> + }
> + out_be32(®s->dsaddr, (u32)data->src);
> + } else
> + out_be32(®s->dsaddr, (u32)data->dest);
> +
Rather than create two different versions of the setup function, which
are about 50% the same, make functions for the stuff above this point
in each of the existing functions, and then do the #ifdef for picking
which to call inside this function.
> +
> +/*
> + * PIO Read/Write Mode reduce the performace as DMA is not used in this mode.
> + */
> +
> +static void
> +esdhc_pio_read_write(struct mmc *mmc, struct mmc_data *data)
> +{
> + volatile struct fsl_esdhc *regs = mmc->priv;
> + uint blocks;
> + uchar* buffer;
> + uint chunk_remain;
> + uint databuf;
> + uint size,irqstat;
> +
> + if (data->flags & MMC_DATA_READ) {
> + blocks = data->blocks;
> + buffer = (uchar*) data->dest;
> + chunk_remain = 0;
> + while(blocks) {
> + size = data->blocksize;
> + irqstat = in_be32(®s->irqstat);
> + while(!(in_be32(®s->prsstat) & PRSSTAT_BREN));
> + while(size && (!(irqstat & IRQSTAT_TC))) {
> + if(chunk_remain == 0) {
> + udelay(1000);
> + irqstat = in_be32(®s->irqstat);
> + databuf = in_be32(®s->datport);
> + chunk_remain =4;
> + }
> + *buffer = databuf & 0xFF;
> + buffer++;
> + databuf >>= 8;
> + size--;
> + chunk_remain--;
> + }
> + blocks--;
> + }
> + } else {
> + blocks = data->blocks;
> + buffer = (uchar*) data->src;
> + chunk_remain = 4;
> + while(blocks) {
> + size = data->blocksize;
> + irqstat = in_be32(®s->irqstat);
> + while(!(in_be32(®s->prsstat) & PRSSTAT_BWEN));
> + while(size && (!(irqstat & IRQSTAT_TC))) {
> + databuf >>=8;
> + databuf |= (u32)*buffer<<24;
> + buffer++;
> + size--;
> + chunk_remain--;
> + if(chunk_remain == 0) {
> + irqstat = in_be32(®s->irqstat);
> + out_be32(®s->datport,databuf);
> + chunk_remain =4;
> + }
> + }
> + blocks--;
> + }
> + }
> +}
> +#endif
Split this into a read function and a write function, and move the
if() statement into the caller.
> +
> static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
> {
> uint wml_value;
> @@ -141,6 +241,23 @@ static int esdhc_setup_data(struct mmc *mmc, struct mmc_data *data)
> return 0;
> }
>
> +static void
> +esdhc_dma_read_write(struct mmc *mmc)
Call this esdhc_wait_dma()
> +{
> + volatile struct fsl_esdhc *regs = mmc->priv;
> + uint irqstat;
> +
> + do {
> + irqstat = in_be32(®s->irqstat);
> +
> + if (irqstat & DATA_ERR)
> + return COMM_ERR;
> +
> + if (irqstat & IRQSTAT_DTOE)
> + return TIMEOUT;
> + } while (!(irqstat & IRQSTAT_TC) &&
> + (in_be32(®s->prsstat) & PRSSTAT_DLA));
> +}
>
> /*
> * Sends a command out on the bus. Takes the mmc pointer,
> @@ -174,7 +291,11 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
> if (data) {
> int err;
>
> +#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
> + err = esdhc_setup_pio_data(mmc, data);
> +#else
> err = esdhc_setup_data(mmc, data);
> +#endif
Using my suggestion above, this would stay the same as it was.
> if(err)
> return err;
> }
> @@ -215,16 +336,11 @@ esdhc_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd, struct mmc_data *data)
>
> /* Wait until all of the blocks are transferred */
> if (data) {
> - do {
> - irqstat = in_be32(®s->irqstat);
> -
> - if (irqstat & DATA_ERR)
> - return COMM_ERR;
> -
> - if (irqstat & IRQSTAT_DTOE)
> - return TIMEOUT;
> - } while (!(irqstat & IRQSTAT_TC) &&
> - (in_be32(®s->prsstat) & PRSSTAT_DLA));
> +#ifdef CONFIG_SYS_FSL_ESDHC_USE_PIO
> + esdhc_pio_read_write(mmc,data);
My suggestion is to put the if-else from read_write here, and call
the read and write functions separately.
Andy
More information about the U-Boot
mailing list