2005-04-16 15:20:36 -07:00
/*
* * linux / amiga / chipram . c
* *
* * Modified 03 - May - 94 by Geert Uytterhoeven < geert @ linux - m68k . org >
* * - 64 - bit aligned allocations for full AGA compatibility
* *
* * Rewritten 15 / 9 / 2000 by Geert to use resource management
*/
# include <linux/types.h>
# include <linux/kernel.h>
2008-07-23 21:28:13 -07:00
# include <linux/mm.h>
2005-04-16 15:20:36 -07:00
# include <linux/init.h>
# include <linux/ioport.h>
# include <linux/slab.h>
# include <linux/string.h>
2008-02-04 22:30:25 -08:00
# include <linux/module.h>
2011-04-24 23:40:51 +02:00
# include <asm/atomic.h>
2005-04-16 15:20:36 -07:00
# include <asm/page.h>
# include <asm/amigahw.h>
unsigned long amiga_chip_size ;
2008-02-04 22:30:25 -08:00
EXPORT_SYMBOL ( amiga_chip_size ) ;
2005-04-16 15:20:36 -07:00
static struct resource chipram_res = {
2011-05-21 20:46:39 +02:00
. name = " Chip RAM " , . start = CHIP_PHYSADDR
2005-04-16 15:20:36 -07:00
} ;
2011-04-24 23:40:51 +02:00
static atomic_t chipavail ;
2005-04-16 15:20:36 -07:00
void __init amiga_chip_init ( void )
{
2011-05-21 20:46:39 +02:00
if ( ! AMIGAHW_PRESENT ( CHIP_RAM ) )
return ;
2005-04-16 15:20:36 -07:00
2011-05-22 11:09:02 +02:00
chipram_res . end = CHIP_PHYSADDR + amiga_chip_size - 1 ;
2011-05-21 20:46:39 +02:00
request_resource ( & iomem_resource , & chipram_res ) ;
2005-04-16 15:20:36 -07:00
2011-04-24 23:40:51 +02:00
atomic_set ( & chipavail , amiga_chip_size ) ;
2005-04-16 15:20:36 -07:00
}
void * amiga_chip_alloc ( unsigned long size , const char * name )
{
2011-05-21 20:46:39 +02:00
struct resource * res ;
2011-04-24 23:19:05 +02:00
void * p ;
2005-04-16 15:20:36 -07:00
2011-05-21 20:46:39 +02:00
res = kzalloc ( sizeof ( struct resource ) , GFP_KERNEL ) ;
if ( ! res )
return NULL ;
2011-04-24 23:19:05 +02:00
res - > name = name ;
p = amiga_chip_alloc_res ( size , res ) ;
if ( ! p ) {
2011-05-21 20:46:39 +02:00
kfree ( res ) ;
return NULL ;
}
2011-04-24 23:19:05 +02:00
return p ;
2005-04-16 15:20:36 -07:00
}
2008-02-04 22:30:25 -08:00
EXPORT_SYMBOL ( amiga_chip_alloc ) ;
2005-04-16 15:20:36 -07:00
2011-05-21 20:46:39 +02:00
/*
* Warning :
* amiga_chip_alloc_res is meant only for drivers that need to
* allocate Chip RAM before kmalloc ( ) is functional . As a consequence ,
* those drivers must not free that Chip RAM afterwards .
*/
2005-04-16 15:20:36 -07:00
2011-04-24 23:19:05 +02:00
void * amiga_chip_alloc_res ( unsigned long size , struct resource * res )
2005-04-16 15:20:36 -07:00
{
2011-04-24 23:19:05 +02:00
int error ;
2005-04-16 15:20:36 -07:00
2011-05-21 20:46:39 +02:00
/* round up */
size = PAGE_ALIGN ( size ) ;
2005-04-16 15:20:36 -07:00
2011-04-24 22:55:20 +02:00
pr_debug ( " amiga_chip_alloc_res: allocate %lu bytes \n " , size ) ;
2011-04-24 23:19:05 +02:00
error = allocate_resource ( & chipram_res , res , size , 0 , UINT_MAX ,
PAGE_SIZE , NULL , NULL ) ;
if ( error < 0 ) {
pr_err ( " amiga_chip_alloc_res: allocate_resource() failed %d! \n " ,
error ) ;
return NULL ;
2011-05-21 20:46:39 +02:00
}
2011-04-24 23:19:05 +02:00
2011-04-24 23:40:51 +02:00
atomic_sub ( size , & chipavail ) ;
2011-04-24 22:55:20 +02:00
pr_debug ( " amiga_chip_alloc_res: returning %pR \n " , res ) ;
2011-05-21 20:46:39 +02:00
return ( void * ) ZTWO_VADDR ( res - > start ) ;
2005-04-16 15:20:36 -07:00
}
void amiga_chip_free ( void * ptr )
{
2011-05-21 20:46:39 +02:00
unsigned long start = ZTWO_PADDR ( ptr ) ;
2011-05-07 20:56:00 +02:00
struct resource * res ;
2011-05-21 20:46:39 +02:00
unsigned long size ;
2011-05-07 20:56:00 +02:00
res = lookup_resource ( & chipram_res , start ) ;
if ( ! res ) {
pr_err ( " amiga_chip_free: trying to free nonexistent region at "
" %p \n " , ptr ) ;
2011-05-21 20:46:39 +02:00
return ;
}
2011-05-07 20:56:00 +02:00
size = resource_size ( res ) ;
pr_debug ( " amiga_chip_free: free %lu bytes at %p \n " , size , ptr ) ;
atomic_add ( size , & chipavail ) ;
release_resource ( res ) ;
kfree ( res ) ;
2005-04-16 15:20:36 -07:00
}
2008-02-04 22:30:25 -08:00
EXPORT_SYMBOL ( amiga_chip_free ) ;
2005-04-16 15:20:36 -07:00
unsigned long amiga_chip_avail ( void )
{
2011-04-24 23:40:51 +02:00
unsigned long n = atomic_read ( & chipavail ) ;
pr_debug ( " amiga_chip_avail : %lu bytes \n " , n ) ;
return n ;
2005-04-16 15:20:36 -07:00
}
2008-02-04 22:30:25 -08:00
EXPORT_SYMBOL ( amiga_chip_avail ) ;