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