dma-mapping.h 3.6 KB
Newer Older
M
Michal Simek 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * Implements the generic device dma API for microblaze and the pci
 *
 * Copyright (C) 2009-2010 Michal Simek <monstr@monstr.eu>
 * Copyright (C) 2009-2010 PetaLogix
 *
 * This file is subject to the terms and conditions of the GNU General
 * Public License. See the file COPYING in the main directory of this
 * archive for more details.
 *
 * This file is base on powerpc and x86 dma-mapping.h versions
 * Copyright (C) 2004 IBM
 */

#ifndef _ASM_MICROBLAZE_DMA_MAPPING_H
#define _ASM_MICROBLAZE_DMA_MAPPING_H

/*
P
Paul Bolle 已提交
19
 * See Documentation/DMA-API-HOWTO.txt and
M
Michal Simek 已提交
20 21 22 23 24 25 26 27 28 29 30
 * Documentation/DMA-API.txt for documentation.
 */

#include <linux/types.h>
#include <linux/cache.h>
#include <linux/mm.h>
#include <linux/scatterlist.h>
#include <linux/dma-debug.h>
#include <linux/dma-attrs.h>
#include <asm/io.h>
#include <asm-generic/dma-coherent.h>
31
#include <asm/cacheflush.h>
M
Michal Simek 已提交
32 33 34 35 36 37 38 39 40 41 42 43 44

#define DMA_ERROR_CODE		(~(dma_addr_t)0x0)

#define __dma_alloc_coherent(dev, gfp, size, handle)	NULL
#define __dma_free_coherent(size, addr)		((void)0)

/*
 * Available generic sets of operations
 */
extern struct dma_map_ops dma_direct_ops;

static inline struct dma_map_ops *get_dma_ops(struct device *dev)
{
45
	return &dma_direct_ops;
M
Michal Simek 已提交
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
}

static inline int dma_supported(struct device *dev, u64 mask)
{
	struct dma_map_ops *ops = get_dma_ops(dev);

	if (unlikely(!ops))
		return 0;
	if (!ops->dma_supported)
		return 1;
	return ops->dma_supported(dev, mask);
}

static inline int dma_set_mask(struct device *dev, u64 dma_mask)
{
	struct dma_map_ops *ops = get_dma_ops(dev);

	if (unlikely(ops == NULL))
		return -EIO;
	if (ops->set_dma_mask)
		return ops->set_dma_mask(dev, dma_mask);
	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
		return -EIO;
	*dev->dma_mask = dma_mask;
	return 0;
}

#include <asm-generic/dma-mapping-common.h>

75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
static inline void __dma_sync(unsigned long paddr,
			      size_t size, enum dma_data_direction direction)
{
	switch (direction) {
	case DMA_TO_DEVICE:
	case DMA_BIDIRECTIONAL:
		flush_dcache_range(paddr, paddr + size);
		break;
	case DMA_FROM_DEVICE:
		invalidate_dcache_range(paddr, paddr + size);
		break;
	default:
		BUG();
	}
}

M
Michal Simek 已提交
91 92 93
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
	struct dma_map_ops *ops = get_dma_ops(dev);
94 95

	debug_dma_mapping_error(dev, dma_addr);
M
Michal Simek 已提交
96 97 98 99 100 101 102 103 104
	if (ops->mapping_error)
		return ops->mapping_error(dev, dma_addr);

	return (dma_addr == DMA_ERROR_CODE);
}

#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)

105 106 107 108 109
#define dma_alloc_coherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)

static inline void *dma_alloc_attrs(struct device *dev, size_t size,
				    dma_addr_t *dma_handle, gfp_t flag,
				    struct dma_attrs *attrs)
M
Michal Simek 已提交
110 111 112 113 114 115
{
	struct dma_map_ops *ops = get_dma_ops(dev);
	void *memory;

	BUG_ON(!ops);

116
	memory = ops->alloc(dev, size, dma_handle, flag, attrs);
M
Michal Simek 已提交
117 118 119 120 121

	debug_dma_alloc_coherent(dev, size, *dma_handle, memory);
	return memory;
}

122 123 124 125 126
#define dma_free_coherent(d,s,c,h) dma_free_attrs(d, s, c, h, NULL)

static inline void dma_free_attrs(struct device *dev, size_t size,
				  void *cpu_addr, dma_addr_t dma_handle,
				  struct dma_attrs *attrs)
M
Michal Simek 已提交
127 128 129 130 131
{
	struct dma_map_ops *ops = get_dma_ops(dev);

	BUG_ON(!ops);
	debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
132
	ops->free(dev, size, cpu_addr, dma_handle, attrs);
M
Michal Simek 已提交
133 134 135 136 137 138
}

static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
		enum dma_data_direction direction)
{
	BUG_ON(direction == DMA_NONE);
139
	__dma_sync(virt_to_phys(vaddr), size, (int)direction);
M
Michal Simek 已提交
140 141 142
}

#endif	/* _ASM_MICROBLAZE_DMA_MAPPING_H */