sh: Add support for SDK7780 board.
[deliverable/linux.git] / arch / sh / mm / consistent.c
CommitLineData
1da177e4
LT
1/*
2 * arch/sh/mm/consistent.c
3 *
8a7bcf0d 4 * Copyright (C) 2004 - 2007 Paul Mundt
1da177e4
LT
5 *
6 * This file is subject to the terms and conditions of the GNU General Public
7 * License. See the file "COPYING" in the main directory of this archive
8 * for more details.
9 */
10#include <linux/mm.h>
11#include <linux/dma-mapping.h>
26ff6c11
PM
12#include <asm/cacheflush.h>
13#include <asm/addrspace.h>
1da177e4
LT
14#include <asm/io.h>
15
6dae2c23 16void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle)
1da177e4
LT
17{
18 struct page *page, *end, *free;
8a7bcf0d 19 void *ret, *vp;
1da177e4
LT
20 int order;
21
22 size = PAGE_ALIGN(size);
23 order = get_order(size);
24
25 page = alloc_pages(gfp, order);
26 if (!page)
27 return NULL;
8dfcc9ba 28 split_page(page, order);
1da177e4
LT
29
30 ret = page_address(page);
31 *handle = virt_to_phys(ret);
32
8a7bcf0d
PM
33 vp = ioremap_nocache(*handle, size);
34 if (!vp) {
35 free_pages((unsigned long)ret, order);
36 return NULL;
37 }
38
39 memset(vp, 0, size);
40
1da177e4
LT
41 /*
42 * We must flush the cache before we pass it on to the device
43 */
8a7bcf0d 44 dma_cache_sync(NULL, ret, size, DMA_BIDIRECTIONAL);
1da177e4
LT
45
46 page = virt_to_page(ret);
47 free = page + (size >> PAGE_SHIFT);
48 end = page + (1 << order);
49
50 while (++page < end) {
1da177e4
LT
51 /* Free any unused pages */
52 if (page >= free) {
53 __free_page(page);
54 }
55 }
56
8a7bcf0d 57 return vp;
1da177e4 58}
8a7bcf0d 59EXPORT_SYMBOL(consistent_alloc);
1da177e4 60
8a7bcf0d 61void consistent_free(void *vaddr, size_t size, dma_addr_t dma_handle)
1da177e4 62{
8a7bcf0d
PM
63 struct page *page;
64 unsigned long addr;
1da177e4 65
8a7bcf0d
PM
66 addr = (unsigned long)phys_to_virt((unsigned long)dma_handle);
67 page = virt_to_page(addr);
68
69 free_pages(addr, get_order(size));
70
71 iounmap(vaddr);
1da177e4 72}
8a7bcf0d 73EXPORT_SYMBOL(consistent_free);
1da177e4
LT
74
75void consistent_sync(void *vaddr, size_t size, int direction)
76{
8a7bcf0d
PM
77#ifdef CONFIG_CPU_SH5
78 void *p1addr = vaddr;
79#else
80 void *p1addr = (void*) P1SEGADDR((unsigned long)vaddr);
81#endif
1da177e4
LT
82
83 switch (direction) {
84 case DMA_FROM_DEVICE: /* invalidate only */
622a9edd 85 __flush_invalidate_region(p1addr, size);
1da177e4
LT
86 break;
87 case DMA_TO_DEVICE: /* writeback only */
622a9edd 88 __flush_wback_region(p1addr, size);
1da177e4
LT
89 break;
90 case DMA_BIDIRECTIONAL: /* writeback and invalidate */
622a9edd 91 __flush_purge_region(p1addr, size);
1da177e4
LT
92 break;
93 default:
94 BUG();
95 }
96}
1da177e4 97EXPORT_SYMBOL(consistent_sync);
This page took 0.283202 seconds and 5 git commands to generate.