2 * arch/sh/cchips/voyagergx/consistent.c
4 * Copyright (C) 2004 Paul Mundt
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
11 #include <linux/dma-mapping.h>
12 #include <linux/slab.h>
13 #include <linux/list.h>
14 #include <linux/types.h>
15 #include <linux/module.h>
16 #include <linux/device.h>
18 #include <asm/bus-sh.h>
20 struct voya_alloc_entry {
21 struct list_head list;
26 static DEFINE_SPINLOCK(voya_list_lock);
27 static LIST_HEAD(voya_alloc_list);
29 #define OHCI_SRAM_START 0xb0000000
30 #define OHCI_HCCA_SIZE 0x100
31 #define OHCI_SRAM_SIZE 0x10000
33 void *voyagergx_consistent_alloc(struct device *dev, size_t size,
34 dma_addr_t *handle, gfp_t flag)
36 struct list_head *list = &voya_alloc_list;
37 struct voya_alloc_entry *entry;
38 struct sh_dev *shdev = to_sh_dev(dev);
39 unsigned long start, end;
43 * The SM501 contains an integrated 8051 with its own SRAM.
44 * Devices within the cchip can all hook into the 8051 SRAM.
45 * We presently use this for the OHCI.
47 * Everything else goes through consistent_alloc().
49 if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
50 (dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
51 shdev->dev_id != SH_DEV_ID_USB_OHCI))
54 start = OHCI_SRAM_START + OHCI_HCCA_SIZE;
56 entry = kmalloc(sizeof(struct voya_alloc_entry), GFP_ATOMIC);
58 return ERR_PTR(-ENOMEM);
60 entry->len = (size + 15) & ~15;
63 * The basis for this allocator is dwmw2's malloc.. the
64 * Matrox allocator :-)
66 spin_lock_irqsave(&voya_list_lock, flags);
67 list_for_each(list, &voya_alloc_list) {
68 struct voya_alloc_entry *p;
70 p = list_entry(list, struct voya_alloc_entry, list);
72 if (p->ofs - start >= size)
75 start = p->ofs + p->len;
78 end = start + (OHCI_SRAM_SIZE - OHCI_HCCA_SIZE);
79 list = &voya_alloc_list;
81 if (end - start >= size) {
84 list_add_tail(&entry->list, list);
85 spin_unlock_irqrestore(&voya_list_lock, flags);
92 spin_unlock_irqrestore(&voya_list_lock, flags);
94 return ERR_PTR(-EINVAL);
97 int voyagergx_consistent_free(struct device *dev, size_t size,
98 void *vaddr, dma_addr_t handle)
100 struct voya_alloc_entry *entry;
101 struct sh_dev *shdev = to_sh_dev(dev);
104 if (!dev || dev->bus != &sh_bus_types[SH_BUS_VIRT] ||
105 (dev->bus == &sh_bus_types[SH_BUS_VIRT] &&
106 shdev->dev_id != SH_DEV_ID_USB_OHCI))
109 spin_lock_irqsave(&voya_list_lock, flags);
110 list_for_each_entry(entry, &voya_alloc_list, list) {
111 if (entry->ofs != handle)
114 list_del(&entry->list);
119 spin_unlock_irqrestore(&voya_list_lock, flags);
124 EXPORT_SYMBOL(voyagergx_consistent_alloc);
125 EXPORT_SYMBOL(voyagergx_consistent_free);