Loading drivers/mmc/host/sdhci.c +72 −91 Original line number Diff line number Diff line Loading @@ -173,119 +173,95 @@ static void sdhci_led_control(struct led_classdev *led, * * \*****************************************************************************/ static inline char* sdhci_sg_to_buffer(struct sdhci_host* host) { return sg_virt(host->cur_sg); } static inline int sdhci_next_sg(struct sdhci_host* host) { /* * Skip to next SG entry. */ host->cur_sg++; host->num_sg--; /* * Any entries left? */ if (host->num_sg > 0) { host->offset = 0; host->remain = host->cur_sg->length; } return host->num_sg; } static void sdhci_read_block_pio(struct sdhci_host *host) { int blksize, chunk_remain; u32 data; char *buffer; int size; unsigned long flags; size_t blksize, len, chunk; u32 scratch; u8 *buf; DBG("PIO reading\n"); blksize = host->data->blksz; chunk_remain = 0; data = 0; chunk = 0; buffer = sdhci_sg_to_buffer(host) + host->offset; local_irq_save(flags); while (blksize) { if (chunk_remain == 0) { data = readl(host->ioaddr + SDHCI_BUFFER); chunk_remain = min(blksize, 4); } if (!sg_miter_next(&host->sg_miter)) BUG(); size = min(host->remain, chunk_remain); len = min(host->sg_miter.length, blksize); chunk_remain -= size; blksize -= size; host->offset += size; host->remain -= size; blksize -= len; host->sg_miter.consumed = len; while (size) { *buffer = data & 0xFF; buffer++; data >>= 8; size--; } buf = host->sg_miter.addr; if (host->remain == 0) { if (sdhci_next_sg(host) == 0) { BUG_ON(blksize != 0); return; while (len) { if (chunk == 0) { scratch = readl(host->ioaddr + SDHCI_BUFFER); chunk = 4; } buffer = sdhci_sg_to_buffer(host); *buf = scratch & 0xFF; buf++; scratch >>= 8; chunk--; len--; } } sg_miter_stop(&host->sg_miter); local_irq_restore(flags); } static void sdhci_write_block_pio(struct sdhci_host *host) { int blksize, chunk_remain; u32 data; char *buffer; int bytes, size; unsigned long flags; size_t blksize, len, chunk; u32 scratch; u8 *buf; DBG("PIO writing\n"); blksize = host->data->blksz; chunk_remain = 4; data = 0; chunk = 0; scratch = 0; bytes = 0; buffer = sdhci_sg_to_buffer(host) + host->offset; local_irq_save(flags); while (blksize) { size = min(host->remain, chunk_remain); if (!sg_miter_next(&host->sg_miter)) BUG(); chunk_remain -= size; blksize -= size; host->offset += size; host->remain -= size; len = min(host->sg_miter.length, blksize); while (size) { data >>= 8; data |= (u32)*buffer << 24; buffer++; size--; } blksize -= len; host->sg_miter.consumed = len; if (chunk_remain == 0) { writel(data, host->ioaddr + SDHCI_BUFFER); chunk_remain = min(blksize, 4); } buf = host->sg_miter.addr; if (host->remain == 0) { if (sdhci_next_sg(host) == 0) { BUG_ON(blksize != 0); return; while (len) { scratch |= (u32)*buf << (chunk * 8); buf++; chunk++; len--; if ((chunk == 4) || ((len == 0) && (blksize == 0))) { writel(scratch, host->ioaddr + SDHCI_BUFFER); chunk = 0; scratch = 0; } buffer = sdhci_sg_to_buffer(host); } } sg_miter_stop(&host->sg_miter); local_irq_restore(flags); } static void sdhci_transfer_pio(struct sdhci_host *host) Loading @@ -294,7 +270,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host) BUG_ON(!host->data); if (host->num_sg == 0) if (host->blocks == 0) return; if (host->data->flags & MMC_DATA_READ) Loading @@ -308,7 +284,8 @@ static void sdhci_transfer_pio(struct sdhci_host *host) else sdhci_write_block_pio(host); if (host->num_sg == 0) host->blocks--; if (host->blocks == 0) break; } Loading Loading @@ -713,11 +690,9 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) } if (!(host->flags & SDHCI_REQ_USE_DMA)) { host->cur_sg = data->sg; host->num_sg = data->sg_len; host->offset = 0; host->remain = host->cur_sg->length; sg_miter_start(&host->sg_miter, data->sg, data->sg_len, SG_MITER_ATOMIC); host->blocks = data->blocks; } /* We do not handle DMA boundaries, so set it to max (512 KiB) */ Loading Loading @@ -1583,9 +1558,15 @@ int sdhci_add_host(struct sdhci_host *host) } } /* XXX: Hack to get MMC layer to avoid highmem */ if (!(host->flags & SDHCI_USE_DMA)) mmc_dev(host->mmc)->dma_mask = NULL; /* * If we use DMA, then it's up to the caller to set the DMA * mask, but PIO does not need the hw shim so we set a new * mask here in that case. */ if (!(host->flags & SDHCI_USE_DMA)) { host->dma_mask = DMA_BIT_MASK(64); mmc_dev(host->mmc)->dma_mask = &host->dma_mask; } host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; Loading drivers/mmc/host/sdhci.h +3 −4 Original line number Diff line number Diff line Loading @@ -212,6 +212,7 @@ struct sdhci_host { /* Internal data */ struct mmc_host *mmc; /* MMC structure */ u64 dma_mask; /* custom DMA mask */ #ifdef CONFIG_LEDS_CLASS struct led_classdev led; /* LED control */ Loading @@ -238,10 +239,8 @@ struct sdhci_host { struct mmc_data *data; /* Current data request */ unsigned int data_early:1; /* Data finished before cmd */ struct scatterlist *cur_sg; /* We're working on this */ int num_sg; /* Entries left */ int offset; /* Offset into current sg */ int remain; /* Bytes left in current */ struct sg_mapping_iter sg_miter; /* SG state for PIO */ unsigned int blocks; /* remaining PIO blocks */ int sg_count; /* Mapped sg entries */ Loading Loading
drivers/mmc/host/sdhci.c +72 −91 Original line number Diff line number Diff line Loading @@ -173,119 +173,95 @@ static void sdhci_led_control(struct led_classdev *led, * * \*****************************************************************************/ static inline char* sdhci_sg_to_buffer(struct sdhci_host* host) { return sg_virt(host->cur_sg); } static inline int sdhci_next_sg(struct sdhci_host* host) { /* * Skip to next SG entry. */ host->cur_sg++; host->num_sg--; /* * Any entries left? */ if (host->num_sg > 0) { host->offset = 0; host->remain = host->cur_sg->length; } return host->num_sg; } static void sdhci_read_block_pio(struct sdhci_host *host) { int blksize, chunk_remain; u32 data; char *buffer; int size; unsigned long flags; size_t blksize, len, chunk; u32 scratch; u8 *buf; DBG("PIO reading\n"); blksize = host->data->blksz; chunk_remain = 0; data = 0; chunk = 0; buffer = sdhci_sg_to_buffer(host) + host->offset; local_irq_save(flags); while (blksize) { if (chunk_remain == 0) { data = readl(host->ioaddr + SDHCI_BUFFER); chunk_remain = min(blksize, 4); } if (!sg_miter_next(&host->sg_miter)) BUG(); size = min(host->remain, chunk_remain); len = min(host->sg_miter.length, blksize); chunk_remain -= size; blksize -= size; host->offset += size; host->remain -= size; blksize -= len; host->sg_miter.consumed = len; while (size) { *buffer = data & 0xFF; buffer++; data >>= 8; size--; } buf = host->sg_miter.addr; if (host->remain == 0) { if (sdhci_next_sg(host) == 0) { BUG_ON(blksize != 0); return; while (len) { if (chunk == 0) { scratch = readl(host->ioaddr + SDHCI_BUFFER); chunk = 4; } buffer = sdhci_sg_to_buffer(host); *buf = scratch & 0xFF; buf++; scratch >>= 8; chunk--; len--; } } sg_miter_stop(&host->sg_miter); local_irq_restore(flags); } static void sdhci_write_block_pio(struct sdhci_host *host) { int blksize, chunk_remain; u32 data; char *buffer; int bytes, size; unsigned long flags; size_t blksize, len, chunk; u32 scratch; u8 *buf; DBG("PIO writing\n"); blksize = host->data->blksz; chunk_remain = 4; data = 0; chunk = 0; scratch = 0; bytes = 0; buffer = sdhci_sg_to_buffer(host) + host->offset; local_irq_save(flags); while (blksize) { size = min(host->remain, chunk_remain); if (!sg_miter_next(&host->sg_miter)) BUG(); chunk_remain -= size; blksize -= size; host->offset += size; host->remain -= size; len = min(host->sg_miter.length, blksize); while (size) { data >>= 8; data |= (u32)*buffer << 24; buffer++; size--; } blksize -= len; host->sg_miter.consumed = len; if (chunk_remain == 0) { writel(data, host->ioaddr + SDHCI_BUFFER); chunk_remain = min(blksize, 4); } buf = host->sg_miter.addr; if (host->remain == 0) { if (sdhci_next_sg(host) == 0) { BUG_ON(blksize != 0); return; while (len) { scratch |= (u32)*buf << (chunk * 8); buf++; chunk++; len--; if ((chunk == 4) || ((len == 0) && (blksize == 0))) { writel(scratch, host->ioaddr + SDHCI_BUFFER); chunk = 0; scratch = 0; } buffer = sdhci_sg_to_buffer(host); } } sg_miter_stop(&host->sg_miter); local_irq_restore(flags); } static void sdhci_transfer_pio(struct sdhci_host *host) Loading @@ -294,7 +270,7 @@ static void sdhci_transfer_pio(struct sdhci_host *host) BUG_ON(!host->data); if (host->num_sg == 0) if (host->blocks == 0) return; if (host->data->flags & MMC_DATA_READ) Loading @@ -308,7 +284,8 @@ static void sdhci_transfer_pio(struct sdhci_host *host) else sdhci_write_block_pio(host); if (host->num_sg == 0) host->blocks--; if (host->blocks == 0) break; } Loading Loading @@ -713,11 +690,9 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) } if (!(host->flags & SDHCI_REQ_USE_DMA)) { host->cur_sg = data->sg; host->num_sg = data->sg_len; host->offset = 0; host->remain = host->cur_sg->length; sg_miter_start(&host->sg_miter, data->sg, data->sg_len, SG_MITER_ATOMIC); host->blocks = data->blocks; } /* We do not handle DMA boundaries, so set it to max (512 KiB) */ Loading Loading @@ -1583,9 +1558,15 @@ int sdhci_add_host(struct sdhci_host *host) } } /* XXX: Hack to get MMC layer to avoid highmem */ if (!(host->flags & SDHCI_USE_DMA)) mmc_dev(host->mmc)->dma_mask = NULL; /* * If we use DMA, then it's up to the caller to set the DMA * mask, but PIO does not need the hw shim so we set a new * mask here in that case. */ if (!(host->flags & SDHCI_USE_DMA)) { host->dma_mask = DMA_BIT_MASK(64); mmc_dev(host->mmc)->dma_mask = &host->dma_mask; } host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; Loading
drivers/mmc/host/sdhci.h +3 −4 Original line number Diff line number Diff line Loading @@ -212,6 +212,7 @@ struct sdhci_host { /* Internal data */ struct mmc_host *mmc; /* MMC structure */ u64 dma_mask; /* custom DMA mask */ #ifdef CONFIG_LEDS_CLASS struct led_classdev led; /* LED control */ Loading @@ -238,10 +239,8 @@ struct sdhci_host { struct mmc_data *data; /* Current data request */ unsigned int data_early:1; /* Data finished before cmd */ struct scatterlist *cur_sg; /* We're working on this */ int num_sg; /* Entries left */ int offset; /* Offset into current sg */ int remain; /* Bytes left in current */ struct sg_mapping_iter sg_miter; /* SG state for PIO */ unsigned int blocks; /* remaining PIO blocks */ int sg_count; /* Mapped sg entries */ Loading