Re: [PATCH v2 14/14] mmc: mmci: Add Qcom specific pio_read function.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Linus W,

On 23/05/14 10:31, Linus Walleij wrote:
static int mmci_qcom_pio_read(struct mmci_host *host, char *buffer,
                         unsigned int remain)
{
        u32 *ptr = (u32*) buffer;
        unsigned int count = 0;
        unsigned int words;
        unsigned int fifo_size = host->variant->fifosize;

        words = DIV_ROUND_UP(remain, 4);
        while (readl(host->base + MMCISTATUS) & MCI_RXDATAAVLBL) {
                *ptr = readl(host->base + MMCIFIFO + (count % fifo_size));
                ptr++;
                count += 4;
                remain--;
                if (!remain)
                        break;
        }
        return count;
}

I guess you will run into additional problems when you come to doing
SDIO. This function can return*more*  bytes than asked for, as it rounds
up. It won't happen with MMC/SD transfers since these are always
divisible by 8, but it*will*  happen on SDIO!
That's a good point,

Qualcomm will need SDIO support in future, so I have slightly modified the code to address this. Other thing I tried was to fit in this in mmci_pio_read, It became very ugly, as the FIFOCNT register behaviour is totally different and there is no way to tell how many bytes are ready to be consumed. So finally I think having a separate pio read for qualcomm looks much neater.

final mmci_qcom_pio_read looks like:


static int mmci_qcom_pio_read(struct mmci_host *host, char *buffer,
            unsigned int remain)
{
    u32 *ptr = (u32*) buffer;
    unsigned int count = 0;
    unsigned int words, bytes;
    unsigned int fifo_size = host->variant->fifosize;

    words = remain >> 2;
    bytes = remain % 4;
    /* read full words followed by leftover bytes */
    if (words) {
        while (readl(host->base + MMCISTATUS) & MCI_RXDATAAVLBL) {
            *ptr = readl(host->base + MMCIFIFO + (count % fifo_size));
            ptr++;
            count += 4;
            words--;
            if (!words)
                break;
         }
    }

    /* read leftover bytes */
    if (unlikely(bytes)) {
        unsigned char buf[4];
        if (readl(host->base + MMCISTATUS) & MCI_RXDATAAVLBL) {
            *buf = readl(host->base + MMCIFIFO + (count % fifo_size));
            memcpy(ptr, buf, bytes);
             count += bytes;
        }
    }

    return count;
}

Thanks,
srini

--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [Linux for Sparc]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux