linux/arch/m68k/amiga/chipram.c
<<
>>
Prefs
   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
  10#include <linux/types.h>
  11#include <linux/kernel.h>
  12#include <linux/mm.h>
  13#include <linux/init.h>
  14#include <linux/ioport.h>
  15#include <linux/slab.h>
  16#include <linux/string.h>
  17#include <linux/module.h>
  18
  19#include <asm/atomic.h>
  20#include <asm/page.h>
  21#include <asm/amigahw.h>
  22
  23unsigned long amiga_chip_size;
  24EXPORT_SYMBOL(amiga_chip_size);
  25
  26static struct resource chipram_res = {
  27        .name = "Chip RAM", .start = CHIP_PHYSADDR
  28};
  29static atomic_t chipavail;
  30
  31
  32void __init amiga_chip_init(void)
  33{
  34        if (!AMIGAHW_PRESENT(CHIP_RAM))
  35                return;
  36
  37        chipram_res.end = CHIP_PHYSADDR + amiga_chip_size - 1;
  38        request_resource(&iomem_resource, &chipram_res);
  39
  40        atomic_set(&chipavail, amiga_chip_size);
  41}
  42
  43
  44void *amiga_chip_alloc(unsigned long size, const char *name)
  45{
  46        struct resource *res;
  47        void *p;
  48
  49        res = kzalloc(sizeof(struct resource), GFP_KERNEL);
  50        if (!res)
  51                return NULL;
  52
  53        res->name = name;
  54        p = amiga_chip_alloc_res(size, res);
  55        if (!p) {
  56                kfree(res);
  57                return NULL;
  58        }
  59
  60        return p;
  61}
  62EXPORT_SYMBOL(amiga_chip_alloc);
  63
  64
  65        /*
  66         *  Warning:
  67         *  amiga_chip_alloc_res is meant only for drivers that need to
  68         *  allocate Chip RAM before kmalloc() is functional. As a consequence,
  69         *  those drivers must not free that Chip RAM afterwards.
  70         */
  71
  72void *amiga_chip_alloc_res(unsigned long size, struct resource *res)
  73{
  74        int error;
  75
  76        /* round up */
  77        size = PAGE_ALIGN(size);
  78
  79        pr_debug("amiga_chip_alloc_res: allocate %lu bytes\n", size);
  80        error = allocate_resource(&chipram_res, res, size, 0, UINT_MAX,
  81                                  PAGE_SIZE, NULL, NULL);
  82        if (error < 0) {
  83                pr_err("amiga_chip_alloc_res: allocate_resource() failed %d!\n",
  84                       error);
  85                return NULL;
  86        }
  87
  88        atomic_sub(size, &chipavail);
  89        pr_debug("amiga_chip_alloc_res: returning %pR\n", res);
  90        return ZTWO_VADDR(res->start);
  91}
  92
  93void amiga_chip_free(void *ptr)
  94{
  95        unsigned long start = ZTWO_PADDR(ptr);
  96        struct resource *res;
  97        unsigned long size;
  98
  99        res = lookup_resource(&chipram_res, start);
 100        if (!res) {
 101                pr_err("amiga_chip_free: trying to free nonexistent region at "
 102                       "%p\n", ptr);
 103                return;
 104        }
 105
 106        size = resource_size(res);
 107        pr_debug("amiga_chip_free: free %lu bytes at %p\n", size, ptr);
 108        atomic_add(size, &chipavail);
 109        release_resource(res);
 110        kfree(res);
 111}
 112EXPORT_SYMBOL(amiga_chip_free);
 113
 114
 115unsigned long amiga_chip_avail(void)
 116{
 117        unsigned long n = atomic_read(&chipavail);
 118
 119        pr_debug("amiga_chip_avail : %lu bytes\n", n);
 120        return n;
 121}
 122EXPORT_SYMBOL(amiga_chip_avail);
 123
 124