void *in_buffer;
const void *out_buffer;
+ /* Slave DMA data width in bytes (4 or 8). */
+ u8 dma_data_width;
u8 hw_num_banks;
ctrl_features = readl(cdns_xspi->iobase + CDNS_XSPI_CTRL_FEATURES_REG);
cdns_xspi->hw_num_banks = FIELD_GET(CDNS_XSPI_NUM_BANKS, ctrl_features);
+ cdns_xspi->dma_data_width = (ctrl_features & CDNS_XSPI_DMA_DATA_WIDTH) ? 8 : 4;
cdns_xspi->set_interrupts_handler(cdns_xspi, false);
return 0;
}
+static inline void cdns_xspi_sdma_read(struct cdns_xspi_dev *cdns_xspi, size_t len)
+{
+ void __iomem *src = cdns_xspi->sdmabase;
+ void *buf = cdns_xspi->in_buffer;
+ size_t offset = 0;
+
+ if (cdns_xspi->dma_data_width == 4) {
+ if (IS_ALIGNED((uintptr_t)src, 4) && IS_ALIGNED((uintptr_t)buf, 4)) {
+ ioread32_rep(src, buf, len >> 2);
+ offset = len & ~0x3;
+ len -= offset;
+ }
+ } else {
+ if (IS_ALIGNED((uintptr_t)src, 8) && IS_ALIGNED((uintptr_t)buf, 8)) {
+ readsq(src, buf, len >> 3);
+ offset = len & ~0x7;
+ len -= offset;
+ }
+ }
+ ioread8_rep(src, (u8 *)buf + offset, len);
+}
+
+static inline void cdns_xspi_sdma_write(struct cdns_xspi_dev *cdns_xspi, size_t len)
+{
+ void __iomem *dst = cdns_xspi->sdmabase;
+ const void *buf = cdns_xspi->out_buffer;
+ size_t offset = 0;
+
+ if (cdns_xspi->dma_data_width == 4) {
+ if (IS_ALIGNED((uintptr_t)dst, 4) && IS_ALIGNED((uintptr_t)buf, 4)) {
+ iowrite32_rep(dst, buf, len >> 2);
+ offset = len & ~0x3;
+ len -= offset;
+ }
+ } else {
+ if (IS_ALIGNED((uintptr_t)dst, 8) && IS_ALIGNED((uintptr_t)buf, 8)) {
+ writesq(dst, buf, len >> 3);
+ offset = len & ~0x7;
+ len -= offset;
+ }
+ }
+ iowrite8_rep(dst, (const u8 *)buf + offset, len);
+}
+
static void cdns_xspi_sdma_handle(struct cdns_xspi_dev *cdns_xspi)
{
u32 sdma_size, sdma_trd_info;
switch (sdma_dir) {
case CDNS_XSPI_SDMA_DIR_READ:
- ioread8_rep(cdns_xspi->sdmabase,
- cdns_xspi->in_buffer, sdma_size);
+ cdns_xspi_sdma_read(cdns_xspi, sdma_size);
break;
case CDNS_XSPI_SDMA_DIR_WRITE:
- iowrite8_rep(cdns_xspi->sdmabase,
- cdns_xspi->out_buffer, sdma_size);
+ cdns_xspi_sdma_write(cdns_xspi, sdma_size);
break;
}
}