18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Functions for ST-RAM allocations 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright 1994-97 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de> 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 78c2ecf20Sopenharmony_ci * License. See the file COPYING in the main directory of this archive 88c2ecf20Sopenharmony_ci * for more details. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/types.h> 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/mm.h> 148c2ecf20Sopenharmony_ci#include <linux/kdev_t.h> 158c2ecf20Sopenharmony_ci#include <linux/major.h> 168c2ecf20Sopenharmony_ci#include <linux/init.h> 178c2ecf20Sopenharmony_ci#include <linux/slab.h> 188c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 198c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 208c2ecf20Sopenharmony_ci#include <linux/memblock.h> 218c2ecf20Sopenharmony_ci#include <linux/mount.h> 228c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 238c2ecf20Sopenharmony_ci#include <linux/module.h> 248c2ecf20Sopenharmony_ci#include <linux/ioport.h> 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include <asm/setup.h> 278c2ecf20Sopenharmony_ci#include <asm/machdep.h> 288c2ecf20Sopenharmony_ci#include <asm/page.h> 298c2ecf20Sopenharmony_ci#include <asm/atarihw.h> 308c2ecf20Sopenharmony_ci#include <asm/atari_stram.h> 318c2ecf20Sopenharmony_ci#include <asm/io.h> 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* 358c2ecf20Sopenharmony_ci * The ST-RAM allocator allocates memory from a pool of reserved ST-RAM of 368c2ecf20Sopenharmony_ci * configurable size, set aside on ST-RAM init. 378c2ecf20Sopenharmony_ci * As long as this pool is not exhausted, allocation of real ST-RAM can be 388c2ecf20Sopenharmony_ci * guaranteed. 398c2ecf20Sopenharmony_ci */ 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* set if kernel is in ST-RAM */ 428c2ecf20Sopenharmony_cistatic int kernel_in_stram; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cistatic struct resource stram_pool = { 458c2ecf20Sopenharmony_ci .name = "ST-RAM Pool" 468c2ecf20Sopenharmony_ci}; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistatic unsigned long pool_size = 1024*1024; 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic unsigned long stram_virt_offset; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_cistatic int __init atari_stram_setup(char *arg) 538c2ecf20Sopenharmony_ci{ 548c2ecf20Sopenharmony_ci if (!MACH_IS_ATARI) 558c2ecf20Sopenharmony_ci return 0; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci pool_size = memparse(arg, NULL); 588c2ecf20Sopenharmony_ci return 0; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ciearly_param("stram_pool", atari_stram_setup); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/* 658c2ecf20Sopenharmony_ci * This init function is called very early by atari/config.c 668c2ecf20Sopenharmony_ci * It initializes some internal variables needed for stram_alloc() 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_civoid __init atari_stram_init(void) 698c2ecf20Sopenharmony_ci{ 708c2ecf20Sopenharmony_ci int i; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci /* 738c2ecf20Sopenharmony_ci * determine whether kernel code resides in ST-RAM 748c2ecf20Sopenharmony_ci * (then ST-RAM is the first memory block at virtual 0x0) 758c2ecf20Sopenharmony_ci */ 768c2ecf20Sopenharmony_ci kernel_in_stram = (m68k_memory[0].addr == 0); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci for (i = 0; i < m68k_num_memory; ++i) { 798c2ecf20Sopenharmony_ci if (m68k_memory[i].addr == 0) { 808c2ecf20Sopenharmony_ci return; 818c2ecf20Sopenharmony_ci } 828c2ecf20Sopenharmony_ci } 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci /* Should never come here! (There is always ST-Ram!) */ 858c2ecf20Sopenharmony_ci panic("atari_stram_init: no ST-RAM found!"); 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci/* 908c2ecf20Sopenharmony_ci * This function is called from setup_arch() to reserve the pages needed for 918c2ecf20Sopenharmony_ci * ST-RAM management, if the kernel resides in ST-RAM. 928c2ecf20Sopenharmony_ci */ 938c2ecf20Sopenharmony_civoid __init atari_stram_reserve_pages(void *start_mem) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci if (kernel_in_stram) { 968c2ecf20Sopenharmony_ci pr_debug("atari_stram pool: kernel in ST-RAM, using alloc_bootmem!\n"); 978c2ecf20Sopenharmony_ci stram_pool.start = (resource_size_t)memblock_alloc_low(pool_size, 988c2ecf20Sopenharmony_ci PAGE_SIZE); 998c2ecf20Sopenharmony_ci if (!stram_pool.start) 1008c2ecf20Sopenharmony_ci panic("%s: Failed to allocate %lu bytes align=%lx\n", 1018c2ecf20Sopenharmony_ci __func__, pool_size, PAGE_SIZE); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci stram_pool.end = stram_pool.start + pool_size - 1; 1048c2ecf20Sopenharmony_ci request_resource(&iomem_resource, &stram_pool); 1058c2ecf20Sopenharmony_ci stram_virt_offset = 0; 1068c2ecf20Sopenharmony_ci pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n", 1078c2ecf20Sopenharmony_ci pool_size, &stram_pool); 1088c2ecf20Sopenharmony_ci pr_debug("atari_stram pool: stram_virt_offset = %lx\n", 1098c2ecf20Sopenharmony_ci stram_virt_offset); 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci} 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci/* 1158c2ecf20Sopenharmony_ci * This function is called as arch initcall to reserve the pages needed for 1168c2ecf20Sopenharmony_ci * ST-RAM management, if the kernel does not reside in ST-RAM. 1178c2ecf20Sopenharmony_ci */ 1188c2ecf20Sopenharmony_ciint __init atari_stram_map_pages(void) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci if (!kernel_in_stram) { 1218c2ecf20Sopenharmony_ci /* 1228c2ecf20Sopenharmony_ci * Skip page 0, as the fhe first 2 KiB are supervisor-only! 1238c2ecf20Sopenharmony_ci */ 1248c2ecf20Sopenharmony_ci pr_debug("atari_stram pool: kernel not in ST-RAM, using ioremap!\n"); 1258c2ecf20Sopenharmony_ci stram_pool.start = PAGE_SIZE; 1268c2ecf20Sopenharmony_ci stram_pool.end = stram_pool.start + pool_size - 1; 1278c2ecf20Sopenharmony_ci request_resource(&iomem_resource, &stram_pool); 1288c2ecf20Sopenharmony_ci stram_virt_offset = (unsigned long) ioremap(stram_pool.start, 1298c2ecf20Sopenharmony_ci resource_size(&stram_pool)) - stram_pool.start; 1308c2ecf20Sopenharmony_ci pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n", 1318c2ecf20Sopenharmony_ci pool_size, &stram_pool); 1328c2ecf20Sopenharmony_ci pr_debug("atari_stram pool: stram_virt_offset = %lx\n", 1338c2ecf20Sopenharmony_ci stram_virt_offset); 1348c2ecf20Sopenharmony_ci } 1358c2ecf20Sopenharmony_ci return 0; 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ciarch_initcall(atari_stram_map_pages); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_civoid *atari_stram_to_virt(unsigned long phys) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci return (void *)(phys + stram_virt_offset); 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ciEXPORT_SYMBOL(atari_stram_to_virt); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ciunsigned long atari_stram_to_phys(void *virt) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci return (unsigned long)(virt - stram_virt_offset); 1508c2ecf20Sopenharmony_ci} 1518c2ecf20Sopenharmony_ciEXPORT_SYMBOL(atari_stram_to_phys); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_civoid *atari_stram_alloc(unsigned long size, const char *owner) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci struct resource *res; 1578c2ecf20Sopenharmony_ci int error; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci pr_debug("atari_stram_alloc: allocate %lu bytes\n", size); 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci /* round up */ 1628c2ecf20Sopenharmony_ci size = PAGE_ALIGN(size); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci res = kzalloc(sizeof(struct resource), GFP_KERNEL); 1658c2ecf20Sopenharmony_ci if (!res) 1668c2ecf20Sopenharmony_ci return NULL; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci res->name = owner; 1698c2ecf20Sopenharmony_ci error = allocate_resource(&stram_pool, res, size, 0, UINT_MAX, 1708c2ecf20Sopenharmony_ci PAGE_SIZE, NULL, NULL); 1718c2ecf20Sopenharmony_ci if (error < 0) { 1728c2ecf20Sopenharmony_ci pr_err("atari_stram_alloc: allocate_resource() failed %d!\n", 1738c2ecf20Sopenharmony_ci error); 1748c2ecf20Sopenharmony_ci kfree(res); 1758c2ecf20Sopenharmony_ci return NULL; 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci pr_debug("atari_stram_alloc: returning %pR\n", res); 1798c2ecf20Sopenharmony_ci return atari_stram_to_virt(res->start); 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ciEXPORT_SYMBOL(atari_stram_alloc); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_civoid atari_stram_free(void *addr) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci unsigned long start = atari_stram_to_phys(addr); 1878c2ecf20Sopenharmony_ci struct resource *res; 1888c2ecf20Sopenharmony_ci unsigned long size; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci res = lookup_resource(&stram_pool, start); 1918c2ecf20Sopenharmony_ci if (!res) { 1928c2ecf20Sopenharmony_ci pr_err("atari_stram_free: trying to free nonexistent region " 1938c2ecf20Sopenharmony_ci "at %p\n", addr); 1948c2ecf20Sopenharmony_ci return; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci size = resource_size(res); 1988c2ecf20Sopenharmony_ci pr_debug("atari_stram_free: free %lu bytes at %p\n", size, addr); 1998c2ecf20Sopenharmony_ci release_resource(res); 2008c2ecf20Sopenharmony_ci kfree(res); 2018c2ecf20Sopenharmony_ci} 2028c2ecf20Sopenharmony_ciEXPORT_SYMBOL(atari_stram_free); 203