2010-10-13 16:00:56 +04:00
/*
* Copyright 2009 - 2010 Freescale Semiconductor , Inc .
*
* Simple memory allocator abstraction for QorIQ ( P1 / P2 ) based Cache - SRAM
*
* Author : Vivek Mahajan < vivek . mahajan @ freescale . com >
*
* This file is derived from the original work done
* by Sylvain Munaut for the Bestcomm SRAM allocator .
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation ; either version 2 of the License , or ( at your
* option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include <linux/kernel.h>
# include <linux/slab.h>
# include <linux/err.h>
# include <linux/of_platform.h>
# include <asm/pgtable.h>
# include <asm/fsl_85xx_cache_sram.h>
# include "fsl_85xx_cache_ctlr.h"
struct mpc85xx_cache_sram * cache_sram ;
void * mpc85xx_cache_sram_alloc ( unsigned int size ,
phys_addr_t * phys , unsigned int align )
{
unsigned long offset ;
unsigned long flags ;
if ( unlikely ( cache_sram = = NULL ) )
return NULL ;
if ( ! size | | ( size > cache_sram - > size ) | | ( align > cache_sram - > size ) ) {
pr_err ( " %s(): size(=%x) or align(=%x) zero or too big \n " ,
__func__ , size , align ) ;
return NULL ;
}
if ( ( align & ( align - 1 ) ) | | align < = 1 ) {
pr_err ( " %s(): align(=%x) must be power of two and >1 \n " ,
__func__ , align ) ;
return NULL ;
}
spin_lock_irqsave ( & cache_sram - > lock , flags ) ;
offset = rh_alloc_align ( cache_sram - > rh , size , align , NULL ) ;
spin_unlock_irqrestore ( & cache_sram - > lock , flags ) ;
if ( IS_ERR_VALUE ( offset ) )
return NULL ;
* phys = cache_sram - > base_phys + offset ;
return ( unsigned char * ) cache_sram - > base_virt + offset ;
}
EXPORT_SYMBOL ( mpc85xx_cache_sram_alloc ) ;
void mpc85xx_cache_sram_free ( void * ptr )
{
unsigned long flags ;
BUG_ON ( ! ptr ) ;
spin_lock_irqsave ( & cache_sram - > lock , flags ) ;
rh_free ( cache_sram - > rh , ptr - cache_sram - > base_virt ) ;
spin_unlock_irqrestore ( & cache_sram - > lock , flags ) ;
}
EXPORT_SYMBOL ( mpc85xx_cache_sram_free ) ;
int __init instantiate_cache_sram ( struct platform_device * dev ,
struct sram_parameters sram_params )
{
int ret = 0 ;
if ( cache_sram ) {
dev_err ( & dev - > dev , " Already initialized cache-sram \n " ) ;
return - EBUSY ;
}
cache_sram = kzalloc ( sizeof ( struct mpc85xx_cache_sram ) , GFP_KERNEL ) ;
if ( ! cache_sram ) {
dev_err ( & dev - > dev , " Out of memory for cache_sram structure \n " ) ;
return - ENOMEM ;
}
cache_sram - > base_phys = sram_params . sram_offset ;
cache_sram - > size = sram_params . sram_size ;
if ( ! request_mem_region ( cache_sram - > base_phys , cache_sram - > size ,
" fsl_85xx_cache_sram " ) ) {
dev_err ( & dev - > dev , " %s: request memory failed \n " ,
dev - > dev . of_node - > full_name ) ;
ret = - ENXIO ;
goto out_free ;
}
2011-05-09 01:43:47 +04:00
cache_sram - > base_virt = ioremap_prot ( cache_sram - > base_phys ,
2010-10-13 16:00:56 +04:00
cache_sram - > size , _PAGE_COHERENT | PAGE_KERNEL ) ;
if ( ! cache_sram - > base_virt ) {
2011-05-09 01:43:47 +04:00
dev_err ( & dev - > dev , " %s: ioremap_prot failed \n " ,
2010-10-13 16:00:56 +04:00
dev - > dev . of_node - > full_name ) ;
ret = - ENOMEM ;
goto out_release ;
}
cache_sram - > rh = rh_create ( sizeof ( unsigned int ) ) ;
if ( IS_ERR ( cache_sram - > rh ) ) {
dev_err ( & dev - > dev , " %s: Unable to create remote heap \n " ,
dev - > dev . of_node - > full_name ) ;
ret = PTR_ERR ( cache_sram - > rh ) ;
goto out_unmap ;
}
rh_attach_region ( cache_sram - > rh , 0 , cache_sram - > size ) ;
spin_lock_init ( & cache_sram - > lock ) ;
dev_info ( & dev - > dev , " [base:0x%llx, size:0x%x] configured and loaded \n " ,
( unsigned long long ) cache_sram - > base_phys , cache_sram - > size ) ;
return 0 ;
out_unmap :
iounmap ( cache_sram - > base_virt ) ;
out_release :
release_mem_region ( cache_sram - > base_phys , cache_sram - > size ) ;
out_free :
kfree ( cache_sram ) ;
return ret ;
}
void remove_cache_sram ( struct platform_device * dev )
{
BUG_ON ( ! cache_sram ) ;
rh_detach_region ( cache_sram - > rh , 0 , cache_sram - > size ) ;
rh_destroy ( cache_sram - > rh ) ;
iounmap ( cache_sram - > base_virt ) ;
release_mem_region ( cache_sram - > base_phys , cache_sram - > size ) ;
kfree ( cache_sram ) ;
cache_sram = NULL ;
dev_info ( & dev - > dev , " MPC85xx Cache-SRAM driver unloaded \n " ) ;
}