···467467 return mv_chan->slots_allocated ? : -ENOMEM;468468}469469470470+/*471471+ * Check if source or destination is an PCIe/IO address (non-SDRAM) and add472472+ * a new MBus window if necessary. Use a cache for these check so that473473+ * the MMIO mapped registers don't have to be accessed for this check474474+ * to speed up this process.475475+ */476476+static int mv_xor_add_io_win(struct mv_xor_chan *mv_chan, u32 addr)477477+{478478+ struct mv_xor_device *xordev = mv_chan->xordev;479479+ void __iomem *base = mv_chan->mmr_high_base;480480+ u32 win_enable;481481+ u32 size;482482+ u8 target, attr;483483+ int ret;484484+ int i;485485+486486+ /* Nothing needs to get done for the Armada 3700 */487487+ if (xordev->xor_type == XOR_ARMADA_37XX)488488+ return 0;489489+490490+ /*491491+ * Loop over the cached windows to check, if the requested area492492+ * is already mapped. If this the case, nothing needs to be done493493+ * and we can return.494494+ */495495+ for (i = 0; i < WINDOW_COUNT; i++) {496496+ if (addr >= xordev->win_start[i] &&497497+ addr <= xordev->win_end[i]) {498498+ /* Window is already mapped */499499+ return 0;500500+ }501501+ }502502+503503+ /*504504+ * The window is not mapped, so we need to create the new mapping505505+ */506506+507507+ /* If no IO window is found that addr has to be located in SDRAM */508508+ ret = mvebu_mbus_get_io_win_info(addr, &size, &target, &attr);509509+ if (ret < 0)510510+ return 0;511511+512512+ /*513513+ * Mask the base addr 'addr' according to 'size' read back from the514514+ * MBus window. Otherwise we might end up with an address located515515+ * somewhere in the middle of this area here.516516+ */517517+ size -= 1;518518+ addr &= ~size;519519+520520+ /*521521+ * Reading one of both enabled register is enough, as they are always522522+ * programmed to the identical values523523+ */524524+ win_enable = readl(base + WINDOW_BAR_ENABLE(0));525525+526526+ /* Set 'i' to the first free window to write the new values to */527527+ i = ffs(~win_enable) - 1;528528+ if (i >= WINDOW_COUNT)529529+ return -ENOMEM;530530+531531+ writel((addr & 0xffff0000) | (attr << 8) | target,532532+ base + WINDOW_BASE(i));533533+ writel(size & 0xffff0000, base + WINDOW_SIZE(i));534534+535535+ /* Fill the caching variables for later use */536536+ xordev->win_start[i] = addr;537537+ xordev->win_end[i] = addr + size;538538+539539+ win_enable |= (1 << i);540540+ win_enable |= 3 << (16 + (2 * i));541541+ writel(win_enable, base + WINDOW_BAR_ENABLE(0));542542+ writel(win_enable, base + WINDOW_BAR_ENABLE(1));543543+544544+ return 0;545545+}546546+470547static struct dma_async_tx_descriptor *471548mv_xor_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,472549 unsigned int src_cnt, size_t len, unsigned long flags)473550{474551 struct mv_xor_chan *mv_chan = to_mv_xor_chan(chan);475552 struct mv_xor_desc_slot *sw_desc;553553+ int ret;476554477555 if (unlikely(len < MV_XOR_MIN_BYTE_COUNT))478556 return NULL;···561483 "%s src_cnt: %d len: %zu dest %pad flags: %ld\n",562484 __func__, src_cnt, len, &dest, flags);563485486486+ /* Check if a new window needs to get added for 'dest' */487487+ ret = mv_xor_add_io_win(mv_chan, dest);488488+ if (ret)489489+ return NULL;490490+564491 sw_desc = mv_chan_alloc_slot(mv_chan);565492 if (sw_desc) {566493 sw_desc->type = DMA_XOR;···573490 mv_desc_init(sw_desc, dest, len, flags);574491 if (mv_chan->op_in_desc == XOR_MODE_IN_DESC)575492 mv_desc_set_mode(sw_desc);576576- while (src_cnt--)493493+ while (src_cnt--) {494494+ /* Check if a new window needs to get added for 'src' */495495+ ret = mv_xor_add_io_win(mv_chan, src[src_cnt]);496496+ if (ret)497497+ return NULL;577498 mv_desc_set_src_addr(sw_desc, src_cnt, src[src_cnt]);499499+ }578500 }579501580502 dev_dbg(mv_chan_to_devp(mv_chan),···1044956 mv_chan->op_in_desc = XOR_MODE_IN_DESC;10459571046958 dma_dev = &mv_chan->dmadev;959959+ mv_chan->xordev = xordev;10479601048961 /*1049962 * These source and destination dummy buffers are used to implement···11711082 (cs->mbus_attr << 8) |11721083 dram->mbus_dram_target_id, base + WINDOW_BASE(i));11731084 writel((cs->size - 1) & 0xffff0000, base + WINDOW_SIZE(i));10851085+10861086+ /* Fill the caching variables for later use */10871087+ xordev->win_start[i] = cs->base;10881088+ xordev->win_end[i] = cs->base + cs->size - 1;1174108911751090 win_enable |= (1 << i);11761091 win_enable |= 3 << (16 + (2 * i));
···1111#ifndef __LINUX_MBUS_H1212#define __LINUX_MBUS_H13131414+#include <linux/errno.h>1515+1416struct resource;15171618struct mbus_dram_target_info···5755#ifdef CONFIG_PLAT_ORION5856extern const struct mbus_dram_target_info *mv_mbus_dram_info(void);5957extern const struct mbus_dram_target_info *mv_mbus_dram_info_nooverlap(void);5858+int mvebu_mbus_get_io_win_info(phys_addr_t phyaddr, u32 *size, u8 *target,5959+ u8 *attr);6060#else6161static inline const struct mbus_dram_target_info *mv_mbus_dram_info(void)6262{···6864{6965 return NULL;7066}6767+static inline int mvebu_mbus_get_io_win_info(phys_addr_t phyaddr, u32 *size,6868+ u8 *target, u8 *attr)6969+{7070+ /*7171+ * On all ARM32 MVEBU platforms with MBus support, this stub7272+ * function will not get called. The real function from the7373+ * MBus driver is called instead. ARM64 MVEBU platforms like7474+ * the Armada 3700 could use the mv_xor device driver which calls7575+ * into this function7676+ */7777+ return -EINVAL;7878+}7179#endif72807381int mvebu_mbus_save_cpu_target(u32 __iomem *store_addr);7482void mvebu_mbus_get_pcie_mem_aperture(struct resource *res);7583void mvebu_mbus_get_pcie_io_aperture(struct resource *res);7684int mvebu_mbus_get_dram_win_info(phys_addr_t phyaddr, u8 *target, u8 *attr);7777-int mvebu_mbus_get_io_win_info(phys_addr_t phyaddr, u32 *size, u8 *target,7878- u8 *attr);7985int mvebu_mbus_add_window_remap_by_id(unsigned int target,8086 unsigned int attribute,8187 phys_addr_t base, size_t size,