1 | /* |
2 | * Functions for ST-RAM allocations |
3 | * |
4 | * Copyright 1994-97 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> |
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 | |
11 | #include <linux/types.h> |
12 | #include <linux/kernel.h> |
13 | #include <linux/mm.h> |
14 | #include <linux/kdev_t.h> |
15 | #include <linux/major.h> |
16 | #include <linux/init.h> |
17 | #include <linux/slab.h> |
18 | #include <linux/vmalloc.h> |
19 | #include <linux/pagemap.h> |
20 | #include <linux/memblock.h> |
21 | #include <linux/mount.h> |
22 | #include <linux/blkdev.h> |
23 | #include <linux/module.h> |
24 | #include <linux/ioport.h> |
25 | |
26 | #include <asm/setup.h> |
27 | #include <asm/machdep.h> |
28 | #include <asm/page.h> |
29 | #include <asm/atarihw.h> |
30 | #include <asm/atari_stram.h> |
31 | #include <asm/io.h> |
32 | |
33 | |
34 | /* |
35 | * The ST-RAM allocator allocates memory from a pool of reserved ST-RAM of |
36 | * configurable size, set aside on ST-RAM init. |
37 | * As long as this pool is not exhausted, allocation of real ST-RAM can be |
38 | * guaranteed. |
39 | */ |
40 | |
41 | /* set if kernel is in ST-RAM */ |
42 | static int kernel_in_stram; |
43 | |
44 | static struct resource stram_pool = { |
45 | .name = "ST-RAM Pool" |
46 | }; |
47 | |
48 | static unsigned long pool_size = 1024*1024; |
49 | |
50 | static unsigned long stram_virt_offset; |
51 | |
52 | static int __init atari_stram_setup(char *arg) |
53 | { |
54 | if (!MACH_IS_ATARI) |
55 | return 0; |
56 | |
57 | pool_size = memparse(ptr: arg, NULL); |
58 | return 0; |
59 | } |
60 | |
61 | early_param("stram_pool" , atari_stram_setup); |
62 | |
63 | |
64 | /* |
65 | * This init function is called very early by atari/config.c |
66 | * It initializes some internal variables needed for stram_alloc() |
67 | */ |
68 | void __init atari_stram_init(void) |
69 | { |
70 | int i; |
71 | |
72 | /* |
73 | * determine whether kernel code resides in ST-RAM |
74 | * (then ST-RAM is the first memory block at virtual 0x0) |
75 | */ |
76 | kernel_in_stram = (m68k_memory[0].addr == 0); |
77 | |
78 | for (i = 0; i < m68k_num_memory; ++i) { |
79 | if (m68k_memory[i].addr == 0) { |
80 | return; |
81 | } |
82 | } |
83 | |
84 | /* Should never come here! (There is always ST-Ram!) */ |
85 | panic(fmt: "atari_stram_init: no ST-RAM found!" ); |
86 | } |
87 | |
88 | |
89 | /* |
90 | * This function is called from setup_arch() to reserve the pages needed for |
91 | * ST-RAM management, if the kernel resides in ST-RAM. |
92 | */ |
93 | void __init atari_stram_reserve_pages(void *start_mem) |
94 | { |
95 | if (kernel_in_stram) { |
96 | pr_debug("atari_stram pool: kernel in ST-RAM, using alloc_bootmem!\n" ); |
97 | stram_pool.start = (resource_size_t)memblock_alloc_low(size: pool_size, |
98 | PAGE_SIZE); |
99 | if (!stram_pool.start) |
100 | panic(fmt: "%s: Failed to allocate %lu bytes align=%lx\n" , |
101 | __func__, pool_size, PAGE_SIZE); |
102 | |
103 | stram_pool.end = stram_pool.start + pool_size - 1; |
104 | request_resource(root: &iomem_resource, new: &stram_pool); |
105 | stram_virt_offset = 0; |
106 | pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n" , |
107 | pool_size, &stram_pool); |
108 | pr_debug("atari_stram pool: stram_virt_offset = %lx\n" , |
109 | stram_virt_offset); |
110 | } |
111 | } |
112 | |
113 | |
114 | /* |
115 | * This function is called as arch initcall to reserve the pages needed for |
116 | * ST-RAM management, if the kernel does not reside in ST-RAM. |
117 | */ |
118 | static int __init atari_stram_map_pages(void) |
119 | { |
120 | if (!kernel_in_stram) { |
121 | /* |
122 | * Skip page 0, as the fhe first 2 KiB are supervisor-only! |
123 | */ |
124 | pr_debug("atari_stram pool: kernel not in ST-RAM, using ioremap!\n" ); |
125 | stram_pool.start = PAGE_SIZE; |
126 | stram_pool.end = stram_pool.start + pool_size - 1; |
127 | request_resource(root: &iomem_resource, new: &stram_pool); |
128 | stram_virt_offset = (unsigned long) ioremap(offset: stram_pool.start, |
129 | size: resource_size(res: &stram_pool)) - stram_pool.start; |
130 | pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n" , |
131 | pool_size, &stram_pool); |
132 | pr_debug("atari_stram pool: stram_virt_offset = %lx\n" , |
133 | stram_virt_offset); |
134 | } |
135 | return 0; |
136 | } |
137 | arch_initcall(atari_stram_map_pages); |
138 | |
139 | |
140 | void *atari_stram_to_virt(unsigned long phys) |
141 | { |
142 | return (void *)(phys + stram_virt_offset); |
143 | } |
144 | EXPORT_SYMBOL(atari_stram_to_virt); |
145 | |
146 | |
147 | unsigned long atari_stram_to_phys(void *virt) |
148 | { |
149 | return (unsigned long)(virt - stram_virt_offset); |
150 | } |
151 | EXPORT_SYMBOL(atari_stram_to_phys); |
152 | |
153 | |
154 | void *atari_stram_alloc(unsigned long size, const char *owner) |
155 | { |
156 | struct resource *res; |
157 | int error; |
158 | |
159 | pr_debug("atari_stram_alloc: allocate %lu bytes\n" , size); |
160 | |
161 | /* round up */ |
162 | size = PAGE_ALIGN(size); |
163 | |
164 | res = kzalloc(size: sizeof(struct resource), GFP_KERNEL); |
165 | if (!res) |
166 | return NULL; |
167 | |
168 | res->name = owner; |
169 | error = allocate_resource(root: &stram_pool, new: res, size, min: 0, UINT_MAX, |
170 | PAGE_SIZE, NULL, NULL); |
171 | if (error < 0) { |
172 | pr_err("atari_stram_alloc: allocate_resource() failed %d!\n" , |
173 | error); |
174 | kfree(objp: res); |
175 | return NULL; |
176 | } |
177 | |
178 | pr_debug("atari_stram_alloc: returning %pR\n" , res); |
179 | return atari_stram_to_virt(phys: res->start); |
180 | } |
181 | EXPORT_SYMBOL(atari_stram_alloc); |
182 | |
183 | |
184 | void atari_stram_free(void *addr) |
185 | { |
186 | unsigned long start = atari_stram_to_phys(virt: addr); |
187 | struct resource *res; |
188 | unsigned long size; |
189 | |
190 | res = lookup_resource(root: &stram_pool, start); |
191 | if (!res) { |
192 | pr_err("atari_stram_free: trying to free nonexistent region " |
193 | "at %p\n" , addr); |
194 | return; |
195 | } |
196 | |
197 | size = resource_size(res); |
198 | pr_debug("atari_stram_free: free %lu bytes at %p\n" , size, addr); |
199 | release_resource(new: res); |
200 | kfree(objp: res); |
201 | } |
202 | EXPORT_SYMBOL(atari_stram_free); |
203 | |