Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | ** linux/amiga/chipram.c | |
3 | ** | |
4 | ** Modified 03-May-94 by Geert Uytterhoeven <geert@linux-m68k.org> | |
5 | ** - 64-bit aligned allocations for full AGA compatibility | |
6 | ** | |
7 | ** Rewritten 15/9/2000 by Geert to use resource management | |
8 | */ | |
9 | ||
1da177e4 LT |
10 | #include <linux/types.h> |
11 | #include <linux/kernel.h> | |
12 | #include <linux/init.h> | |
13 | #include <linux/ioport.h> | |
14 | #include <linux/slab.h> | |
15 | #include <linux/string.h> | |
8b169fa2 AB |
16 | #include <linux/module.h> |
17 | ||
1da177e4 LT |
18 | #include <asm/page.h> |
19 | #include <asm/amigahw.h> | |
20 | ||
21 | unsigned long amiga_chip_size; | |
8b169fa2 | 22 | EXPORT_SYMBOL(amiga_chip_size); |
1da177e4 LT |
23 | |
24 | static struct resource chipram_res = { | |
25 | .name = "Chip RAM", .start = CHIP_PHYSADDR | |
26 | }; | |
27 | static unsigned long chipavail; | |
28 | ||
29 | ||
30 | void __init amiga_chip_init(void) | |
31 | { | |
32 | if (!AMIGAHW_PRESENT(CHIP_RAM)) | |
33 | return; | |
34 | ||
1da177e4 LT |
35 | /* |
36 | * Remove the first 4 pages where PPC exception handlers will be located | |
37 | */ | |
38 | amiga_chip_size -= 0x4000; | |
1da177e4 LT |
39 | chipram_res.end = amiga_chip_size-1; |
40 | request_resource(&iomem_resource, &chipram_res); | |
41 | ||
42 | chipavail = amiga_chip_size; | |
43 | } | |
44 | ||
45 | ||
46 | void *amiga_chip_alloc(unsigned long size, const char *name) | |
47 | { | |
48 | struct resource *res; | |
49 | ||
50 | /* round up */ | |
51 | size = PAGE_ALIGN(size); | |
52 | ||
53 | #ifdef DEBUG | |
54 | printk("amiga_chip_alloc: allocate %ld bytes\n", size); | |
55 | #endif | |
8bcbdf60 | 56 | res = kzalloc(sizeof(struct resource), GFP_KERNEL); |
1da177e4 LT |
57 | if (!res) |
58 | return NULL; | |
1da177e4 LT |
59 | res->name = name; |
60 | ||
61 | if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) { | |
62 | kfree(res); | |
63 | return NULL; | |
64 | } | |
65 | chipavail -= size; | |
66 | #ifdef DEBUG | |
67 | printk("amiga_chip_alloc: returning %lx\n", res->start); | |
68 | #endif | |
69 | return (void *)ZTWO_VADDR(res->start); | |
70 | } | |
8b169fa2 | 71 | EXPORT_SYMBOL(amiga_chip_alloc); |
1da177e4 LT |
72 | |
73 | ||
74 | /* | |
75 | * Warning: | |
76 | * amiga_chip_alloc_res is meant only for drivers that need to allocate | |
77 | * Chip RAM before kmalloc() is functional. As a consequence, those | |
78 | * drivers must not free that Chip RAM afterwards. | |
79 | */ | |
80 | ||
81 | void * __init amiga_chip_alloc_res(unsigned long size, struct resource *res) | |
82 | { | |
83 | unsigned long start; | |
84 | ||
85 | /* round up */ | |
86 | size = PAGE_ALIGN(size); | |
87 | /* dmesg into chipmem prefers memory at the safe end */ | |
88 | start = CHIP_PHYSADDR + chipavail - size; | |
89 | ||
90 | #ifdef DEBUG | |
91 | printk("amiga_chip_alloc_res: allocate %ld bytes\n", size); | |
92 | #endif | |
93 | if (allocate_resource(&chipram_res, res, size, start, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) { | |
94 | printk("amiga_chip_alloc_res: first alloc failed!\n"); | |
95 | if (allocate_resource(&chipram_res, res, size, 0, UINT_MAX, PAGE_SIZE, NULL, NULL) < 0) | |
96 | return NULL; | |
97 | } | |
98 | chipavail -= size; | |
99 | #ifdef DEBUG | |
100 | printk("amiga_chip_alloc_res: returning %lx\n", res->start); | |
101 | #endif | |
102 | return (void *)ZTWO_VADDR(res->start); | |
103 | } | |
104 | ||
105 | void amiga_chip_free(void *ptr) | |
106 | { | |
107 | unsigned long start = ZTWO_PADDR(ptr); | |
108 | struct resource **p, *res; | |
109 | unsigned long size; | |
110 | ||
111 | for (p = &chipram_res.child; (res = *p); p = &res->sibling) { | |
112 | if (res->start != start) | |
113 | continue; | |
114 | *p = res->sibling; | |
115 | size = res->end-start; | |
116 | #ifdef DEBUG | |
117 | printk("amiga_chip_free: free %ld bytes at %p\n", size, ptr); | |
118 | #endif | |
119 | chipavail += size; | |
120 | kfree(res); | |
121 | return; | |
122 | } | |
123 | printk("amiga_chip_free: trying to free nonexistent region at %p\n", ptr); | |
124 | } | |
8b169fa2 | 125 | EXPORT_SYMBOL(amiga_chip_free); |
1da177e4 LT |
126 | |
127 | ||
128 | unsigned long amiga_chip_avail(void) | |
129 | { | |
130 | #ifdef DEBUG | |
131 | printk("amiga_chip_avail : %ld bytes\n", chipavail); | |
132 | #endif | |
133 | return chipavail; | |
134 | } | |
8b169fa2 AB |
135 | EXPORT_SYMBOL(amiga_chip_avail); |
136 |