diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index a09840d0c221..8ce9a52d365b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c @@ -1757,8 +1757,7 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt) buf += len; cnt -= len; if (host->part_buf_count == 2) { - mci_writew(host, DATA(host->data_offset), - host->part_buf16); + mci_fifo_writew(host->fifo_reg, host->part_buf16); host->part_buf_count = 0; } } @@ -1775,15 +1774,14 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt) cnt -= len; /* push data from aligned buffer into fifo */ for (i = 0; i < items; ++i) - mci_writew(host, DATA(host->data_offset), - aligned_buf[i]); + mci_fifo_writew(host->fifo_reg, aligned_buf[i]); } } else #endif { u16 *pdata = buf; for (; cnt >= 2; cnt -= 2) - mci_writew(host, DATA(host->data_offset), *pdata++); + mci_fifo_writew(host->fifo_reg, *pdata++); buf = pdata; } /* put anything remaining in the part_buf */ @@ -1792,8 +1790,7 @@ static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt) /* Push data if we have reached the expected data length */ if ((data->bytes_xfered + init_cnt) == (data->blksz * data->blocks)) - mci_writew(host, DATA(host->data_offset), - host->part_buf16); + mci_fifo_writew(host->fifo_reg, host->part_buf16); } } @@ -1808,8 +1805,7 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt) int items = len >> 1; int i; for (i = 0; i < items; ++i) - aligned_buf[i] = mci_readw(host, - DATA(host->data_offset)); + aligned_buf[i] = mci_fifo_readw(host->fifo_reg); /* memcpy from aligned buffer into output buffer */ memcpy(buf, aligned_buf, len); buf += len; @@ -1820,11 +1816,11 @@ static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt) { u16 *pdata = buf; for (; cnt >= 2; cnt -= 2) - *pdata++ = mci_readw(host, DATA(host->data_offset)); + *pdata++ = mci_fifo_readw(host->fifo_reg); buf = pdata; } if (cnt) { - host->part_buf16 = mci_readw(host, DATA(host->data_offset)); + host->part_buf16 = mci_fifo_readw(host->fifo_reg); dw_mci_pull_final_bytes(host, buf, cnt); } } @@ -1840,8 +1836,7 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt) buf += len; cnt -= len; if (host->part_buf_count == 4) { - mci_writel(host, DATA(host->data_offset), - host->part_buf32); + mci_fifo_writel(host->fifo_reg, host->part_buf32); host->part_buf_count = 0; } } @@ -1858,15 +1853,14 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt) cnt -= len; /* push data from aligned buffer into fifo */ for (i = 0; i < items; ++i) - mci_writel(host, DATA(host->data_offset), - aligned_buf[i]); + mci_fifo_writel(host->fifo_reg, aligned_buf[i]); } } else #endif { u32 *pdata = buf; for (; cnt >= 4; cnt -= 4) - mci_writel(host, DATA(host->data_offset), *pdata++); + mci_fifo_writel(host->fifo_reg, *pdata++); buf = pdata; } /* put anything remaining in the part_buf */ @@ -1875,8 +1869,7 @@ static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt) /* Push data if we have reached the expected data length */ if ((data->bytes_xfered + init_cnt) == (data->blksz * data->blocks)) - mci_writel(host, DATA(host->data_offset), - host->part_buf32); + mci_fifo_writel(host->fifo_reg, host->part_buf32); } } @@ -1891,8 +1884,7 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt) int items = len >> 2; int i; for (i = 0; i < items; ++i) - aligned_buf[i] = mci_readl(host, - DATA(host->data_offset)); + aligned_buf[i] = mci_fifo_readl(host->fifo_reg); /* memcpy from aligned buffer into output buffer */ memcpy(buf, aligned_buf, len); buf += len; @@ -1903,11 +1895,11 @@ static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt) { u32 *pdata = buf; for (; cnt >= 4; cnt -= 4) - *pdata++ = mci_readl(host, DATA(host->data_offset)); + *pdata++ = mci_fifo_readl(host->fifo_reg); buf = pdata; } if (cnt) { - host->part_buf32 = mci_readl(host, DATA(host->data_offset)); + host->part_buf32 = mci_fifo_readl(host->fifo_reg); dw_mci_pull_final_bytes(host, buf, cnt); } } @@ -1924,8 +1916,7 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt) cnt -= len; if (host->part_buf_count == 8) { - mci_writeq(host, DATA(host->data_offset), - host->part_buf); + mci_fifo_writeq(host->fifo_reg, host->part_buf); host->part_buf_count = 0; } } @@ -1942,15 +1933,14 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt) cnt -= len; /* push data from aligned buffer into fifo */ for (i = 0; i < items; ++i) - mci_writeq(host, DATA(host->data_offset), - aligned_buf[i]); + mci_fifo_writeq(host->fifo_reg, aligned_buf[i]); } } else #endif { u64 *pdata = buf; for (; cnt >= 8; cnt -= 8) - mci_writeq(host, DATA(host->data_offset), *pdata++); + mci_fifo_writeq(host->fifo_reg, *pdata++); buf = pdata; } /* put anything remaining in the part_buf */ @@ -1959,8 +1949,7 @@ static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt) /* Push data if we have reached the expected data length */ if ((data->bytes_xfered + init_cnt) == (data->blksz * data->blocks)) - mci_writeq(host, DATA(host->data_offset), - host->part_buf); + mci_fifo_writeq(host->fifo_reg, host->part_buf); } } @@ -1975,8 +1964,8 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt) int items = len >> 3; int i; for (i = 0; i < items; ++i) - aligned_buf[i] = mci_readq(host, - DATA(host->data_offset)); + aligned_buf[i] = mci_fifo_readq(host->fifo_reg); + /* memcpy from aligned buffer into output buffer */ memcpy(buf, aligned_buf, len); buf += len; @@ -1987,11 +1976,11 @@ static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt) { u64 *pdata = buf; for (; cnt >= 8; cnt -= 8) - *pdata++ = mci_readq(host, DATA(host->data_offset)); + *pdata++ = mci_fifo_readq(host->fifo_reg); buf = pdata; } if (cnt) { - host->part_buf = mci_readq(host, DATA(host->data_offset)); + host->part_buf = mci_fifo_readq(host->fifo_reg); dw_mci_pull_final_bytes(host, buf, cnt); } } @@ -2852,9 +2841,9 @@ int dw_mci_probe(struct dw_mci *host) dev_info(host->dev, "Version ID is %04x\n", host->verid); if (host->verid < DW_MMC_240A) - host->data_offset = DATA_OFFSET; + host->fifo_reg = host->regs + DATA_OFFSET; else - host->data_offset = DATA_240A_OFFSET; + host->fifo_reg = host->regs + DATA_240A_OFFSET; tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); ret = devm_request_irq(host->dev, host->irq, dw_mci_interrupt, diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h index b8051d049fb7..f45ab91de339 100644 --- a/drivers/mmc/host/dw_mmc.h +++ b/drivers/mmc/host/dw_mmc.h @@ -169,6 +169,16 @@ #define SDMMC_CTRL_ALL_RESET_FLAGS \ (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | SDMMC_CTRL_DMA_RESET) +/* FIFO register access macros. These should not change the data endian-ness + * as they are written to memory to be dealt with by the upper layers */ +#define mci_fifo_readw(__reg) __raw_readw(__reg) +#define mci_fifo_readl(__reg) __raw_readl(__reg) +#define mci_fifo_readq(__reg) __raw_readq(__reg) + +#define mci_fifo_writew(__value, __reg) __raw_writew(__reg, __value) +#define mci_fifo_writel(__value, __reg) __raw_writel(__reg, __value) +#define mci_fifo_writeq(__value, __reg) __raw_writeq(__reg, __value) + /* Register access macros */ #define mci_readl(dev, reg) \ readl_relaxed((dev)->regs + SDMMC_##reg) @@ -200,6 +210,10 @@ (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg)) #define mci_writeq(dev, reg, value) \ (*(volatile u64 __force *)((dev)->regs + SDMMC_##reg) = (value)) + +#define __raw_writeq(__value, __reg) \ + (*(volatile u64 __force *)(__reg) = (__value)) +#define __raw_readq(__reg) (*(volatile u64 __force *)(__reg)) #endif extern int dw_mci_probe(struct dw_mci *host); diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h index 9efc567e3ced..12111993a317 100644 --- a/include/linux/mmc/dw_mmc.h +++ b/include/linux/mmc/dw_mmc.h @@ -44,6 +44,7 @@ struct mmc_data; * struct dw_mci - MMC controller state shared between all slots * @lock: Spinlock protecting the queue and associated data. * @regs: Pointer to MMIO registers. + * @fifo_reg: Pointer to MMIO registers for data FIFO * @sg: Scatterlist entry currently being processed by PIO code, if any. * @sg_miter: PIO mapping scatterlist iterator. * @cur_slot: The slot which is currently using the controller. @@ -79,7 +80,6 @@ struct mmc_data; * @current_speed: Configured rate of the controller. * @num_slots: Number of slots available. * @verid: Denote Version ID. - * @data_offset: Set the offset of DATA register according to VERID. * @dev: Device associated with the MMC controller. * @pdata: Platform data associated with the MMC controller. * @drv_data: Driver specific data for identified variant of the controller @@ -132,6 +132,7 @@ struct dw_mci { spinlock_t lock; spinlock_t irq_lock; void __iomem *regs; + void __iomem *fifo_reg; struct scatterlist *sg; struct sg_mapping_iter sg_miter; @@ -172,7 +173,6 @@ struct dw_mci { u32 num_slots; u32 fifoth_val; u16 verid; - u16 data_offset; struct device *dev; struct dw_mci_board *pdata; const struct dw_mci_drv_data *drv_data;