diff options
author | Ganesan Ramalingam <ganesanr@broadcom.com> | 2013-06-10 10:28:09 +0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2013-06-13 19:46:40 +0400 |
commit | 79f8511c83f13689913f54d2f189297c226ec064 (patch) | |
tree | 2dc7e379aa8e4284c651194ed200c9cf919afc0d /arch | |
parent | 4954a9a211f1863e3ca3958fd56ad06e1bddc22d (diff) | |
download | linux-79f8511c83f13689913f54d2f189297c226ec064.tar.xz |
MIPS: Netlogic: SWIOTLB dma ops for 32-bit DMA
Add SWIOTLB config option and related files to Netlogic platform.
Some XLP SoC components like the SD/MMC interface cannot do DMA beyond
32-bit physical address. The SD/MMC driver can use memory outside this
range for IO, to support this we have to add bounce buffers implemented
by SWIOTLB.
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
Cc: linux-mips@linux-mips.org
Cc: Ganesan Ramalingam <ganesanr@broadcom.com>
Patchwork: https://patchwork.linux-mips.org/patch/5410/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/include/asm/netlogic/common.h | 3 | ||||
-rw-r--r-- | arch/mips/netlogic/Kconfig | 11 | ||||
-rw-r--r-- | arch/mips/netlogic/common/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/netlogic/common/nlm-dma.c | 107 |
4 files changed, 122 insertions, 0 deletions
diff --git a/arch/mips/include/asm/netlogic/common.h b/arch/mips/include/asm/netlogic/common.h index aef560a51a7e..70351b95ef88 100644 --- a/arch/mips/include/asm/netlogic/common.h +++ b/arch/mips/include/asm/netlogic/common.h @@ -76,6 +76,9 @@ void nlm_node_init(int node); extern struct plat_smp_ops nlm_smp_ops; extern char nlm_reset_entry[], nlm_reset_entry_end[]; +/* SWIOTLB */ +extern struct dma_map_ops nlm_swiotlb_dma_ops; + extern unsigned int nlm_threads_per_core; extern cpumask_t nlm_cpumask; diff --git a/arch/mips/netlogic/Kconfig b/arch/mips/netlogic/Kconfig index e0873a31ebaa..2447bf97d35a 100644 --- a/arch/mips/netlogic/Kconfig +++ b/arch/mips/netlogic/Kconfig @@ -51,4 +51,15 @@ endif config NLM_COMMON bool +config IOMMU_HELPER + bool + +config NEED_SG_DMA_LENGTH + bool + +config SWIOTLB + def_bool y + select NEED_SG_DMA_LENGTH + select IOMMU_HELPER + endif diff --git a/arch/mips/netlogic/common/Makefile b/arch/mips/netlogic/common/Makefile index 291372a086f5..b29549741e05 100644 --- a/arch/mips/netlogic/common/Makefile +++ b/arch/mips/netlogic/common/Makefile @@ -1,3 +1,4 @@ obj-y += irq.o time.o +obj-y += nlm-dma.o obj-$(CONFIG_SMP) += smp.o smpboot.o obj-$(CONFIG_EARLY_PRINTK) += earlycons.o diff --git a/arch/mips/netlogic/common/nlm-dma.c b/arch/mips/netlogic/common/nlm-dma.c new file mode 100644 index 000000000000..f3d4ae87abc7 --- /dev/null +++ b/arch/mips/netlogic/common/nlm-dma.c @@ -0,0 +1,107 @@ +/* +* Copyright (C) 2003-2013 Broadcom Corporation +* All Rights Reserved + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the Broadcom + * license below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <linux/dma-mapping.h> +#include <linux/scatterlist.h> +#include <linux/bootmem.h> +#include <linux/export.h> +#include <linux/swiotlb.h> +#include <linux/types.h> +#include <linux/init.h> +#include <linux/mm.h> + +#include <asm/bootinfo.h> + +static char *nlm_swiotlb; + +static void *nlm_dma_alloc_coherent(struct device *dev, size_t size, + dma_addr_t *dma_handle, gfp_t gfp, struct dma_attrs *attrs) +{ + void *ret; + + if (dma_alloc_from_coherent(dev, size, dma_handle, &ret)) + return ret; + + /* ignore region specifiers */ + gfp &= ~(__GFP_DMA | __GFP_DMA32 | __GFP_HIGHMEM); + +#ifdef CONFIG_ZONE_DMA32 + if (dev->coherent_dma_mask <= DMA_BIT_MASK(32)) + gfp |= __GFP_DMA32; +#endif + + /* Don't invoke OOM killer */ + gfp |= __GFP_NORETRY; + + return swiotlb_alloc_coherent(dev, size, dma_handle, gfp); +} + +static void nlm_dma_free_coherent(struct device *dev, size_t size, + void *vaddr, dma_addr_t dma_handle, struct dma_attrs *attrs) +{ + int order = get_order(size); + + if (dma_release_from_coherent(dev, order, vaddr)) + return; + + swiotlb_free_coherent(dev, size, vaddr, dma_handle); +} + +struct dma_map_ops nlm_swiotlb_dma_ops = { + .alloc = nlm_dma_alloc_coherent, + .free = nlm_dma_free_coherent, + .map_page = swiotlb_map_page, + .unmap_page = swiotlb_unmap_page, + .map_sg = swiotlb_map_sg_attrs, + .unmap_sg = swiotlb_unmap_sg_attrs, + .sync_single_for_cpu = swiotlb_sync_single_for_cpu, + .sync_single_for_device = swiotlb_sync_single_for_device, + .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, + .sync_sg_for_device = swiotlb_sync_sg_for_device, + .mapping_error = swiotlb_dma_mapping_error, + .dma_supported = swiotlb_dma_supported +}; + +void __init plat_swiotlb_setup(void) +{ + size_t swiotlbsize; + unsigned long swiotlb_nslabs; + + swiotlbsize = 1 << 20; /* 1 MB for now */ + swiotlb_nslabs = swiotlbsize >> IO_TLB_SHIFT; + swiotlb_nslabs = ALIGN(swiotlb_nslabs, IO_TLB_SEGSIZE); + swiotlbsize = swiotlb_nslabs << IO_TLB_SHIFT; + + nlm_swiotlb = alloc_bootmem_low_pages(swiotlbsize); + swiotlb_init_with_tbl(nlm_swiotlb, swiotlb_nslabs, 1); +} |