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
, int 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
);