blob: e5a8dbc9abafbe8b41918d3bc7750c6e496667bd [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
Linus Torvalds1da177e2005-04-16 15:20:36 -070010#include <linux/types.h>
11#include <linux/kernel.h>
Andrea Righi27ac7922008-07-23 21:28:13 -070012#include <linux/mm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070013#include <linux/init.h>
14#include <linux/ioport.h>
15#include <linux/slab.h>
16#include <linux/string.h>
Adrian Bunk8b169fa2008-02-04 22:30:25 -080017#include <linux/module.h>
18
Linus Torvalds1da177e2005-04-16 15:20:36 -070019#include <asm/page.h>
20#include <asm/amigahw.h>
21
22unsigned long amiga_chip_size;
Adrian Bunk8b169fa2008-02-04 22:30:25 -080023EXPORT_SYMBOL(amiga_chip_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
25static struct resource chipram_res = {
Geert Uytterhoeven5be32462011-05-21 20:46:39 +020026 .name = "Chip RAM", .start = CHIP_PHYSADDR
Linus Torvalds1da177e2005-04-16 15:20:36 -070027};
28static unsigned long chipavail;
29
30
31void __init amiga_chip_init(void)
32{
Geert Uytterhoeven5be32462011-05-21 20:46:39 +020033 if (!AMIGAHW_PRESENT(CHIP_RAM))
34 return;
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
Geert Uytterhoeven5be32462011-05-21 20:46:39 +020036 chipram_res.end = amiga_chip_size-1;
37 request_resource(&iomem_resource, &chipram_res);
Linus Torvalds1da177e2005-04-16 15:20:36 -070038
Geert Uytterhoeven5be32462011-05-21 20:46:39 +020039 chipavail = amiga_chip_size;
Linus Torvalds1da177e2005-04-16 15:20:36 -070040}
41
42
43void *amiga_chip_alloc(unsigned long size, const char *name)
44{
Geert Uytterhoeven5be32462011-05-21 20:46:39 +020045 struct resource *res;
Geert Uytterhoeven3a17bfa2011-04-24 23:19:05 +020046 void *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
Geert Uytterhoeven5be32462011-05-21 20:46:39 +020048 res = kzalloc(sizeof(struct resource), GFP_KERNEL);
49 if (!res)
50 return NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -070051
Geert Uytterhoeven3a17bfa2011-04-24 23:19:05 +020052 res->name = name;
53 p = amiga_chip_alloc_res(size, res);
54 if (!p) {
Geert Uytterhoeven5be32462011-05-21 20:46:39 +020055 kfree(res);
56 return NULL;
57 }
Geert Uytterhoeven3a17bfa2011-04-24 23:19:05 +020058
59 return p;
Linus Torvalds1da177e2005-04-16 15:20:36 -070060}
Adrian Bunk8b169fa2008-02-04 22:30:25 -080061EXPORT_SYMBOL(amiga_chip_alloc);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
63
Geert Uytterhoeven5be32462011-05-21 20:46:39 +020064 /*
65 * Warning:
66 * amiga_chip_alloc_res is meant only for drivers that need to
67 * allocate Chip RAM before kmalloc() is functional. As a consequence,
68 * those drivers must not free that Chip RAM afterwards.
69 */
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
Geert Uytterhoeven3a17bfa2011-04-24 23:19:05 +020071void *amiga_chip_alloc_res(unsigned long size, struct resource *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -070072{
Geert Uytterhoeven3a17bfa2011-04-24 23:19:05 +020073 int error;
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
Geert Uytterhoeven5be32462011-05-21 20:46:39 +020075 /* round up */
76 size = PAGE_ALIGN(size);
Linus Torvalds1da177e2005-04-16 15:20:36 -070077
Geert Uytterhoevenb4f6f452011-04-24 22:55:20 +020078 pr_debug("amiga_chip_alloc_res: allocate %lu bytes\n", size);
Geert Uytterhoeven3a17bfa2011-04-24 23:19:05 +020079 error = allocate_resource(&chipram_res, res, size, 0, UINT_MAX,
80 PAGE_SIZE, NULL, NULL);
81 if (error < 0) {
82 pr_err("amiga_chip_alloc_res: allocate_resource() failed %d!\n",
83 error);
84 return NULL;
Geert Uytterhoeven5be32462011-05-21 20:46:39 +020085 }
Geert Uytterhoeven3a17bfa2011-04-24 23:19:05 +020086
Geert Uytterhoeven5be32462011-05-21 20:46:39 +020087 chipavail -= size;
Geert Uytterhoevenb4f6f452011-04-24 22:55:20 +020088 pr_debug("amiga_chip_alloc_res: returning %pR\n", res);
Geert Uytterhoeven5be32462011-05-21 20:46:39 +020089 return (void *)ZTWO_VADDR(res->start);
Linus Torvalds1da177e2005-04-16 15:20:36 -070090}
91
92void amiga_chip_free(void *ptr)
93{
Geert Uytterhoeven5be32462011-05-21 20:46:39 +020094 unsigned long start = ZTWO_PADDR(ptr);
95 struct resource **p, *res;
96 unsigned long size;
Linus Torvalds1da177e2005-04-16 15:20:36 -070097
Geert Uytterhoeven5be32462011-05-21 20:46:39 +020098 for (p = &chipram_res.child; (res = *p); p = &res->sibling) {
99 if (res->start != start)
100 continue;
101 *p = res->sibling;
102 size = res->end-start;
Geert Uytterhoevenb4f6f452011-04-24 22:55:20 +0200103 pr_debug("amiga_chip_free: free %lu bytes at %p\n", size, ptr);
Geert Uytterhoeven5be32462011-05-21 20:46:39 +0200104 chipavail += size;
105 kfree(res);
106 return;
107 }
Geert Uytterhoevenb4f6f452011-04-24 22:55:20 +0200108 pr_err("amiga_chip_free: trying to free nonexistent region at %p\n",
Geert Uytterhoeven5be32462011-05-21 20:46:39 +0200109 ptr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700110}
Adrian Bunk8b169fa2008-02-04 22:30:25 -0800111EXPORT_SYMBOL(amiga_chip_free);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112
113
114unsigned long amiga_chip_avail(void)
115{
Geert Uytterhoevenb4f6f452011-04-24 22:55:20 +0200116 pr_debug("amiga_chip_avail : %lu bytes\n", chipavail);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117 return chipavail;
118}
Adrian Bunk8b169fa2008-02-04 22:30:25 -0800119EXPORT_SYMBOL(amiga_chip_avail);
120