2005-06-23 03:43:31 +04:00
/*
2005-11-01 04:08:37 +03:00
* memory mapped NVRAM
2005-06-23 03:43:31 +04:00
*
* ( C ) Copyright IBM Corp . 2005
*
* Authors : Utz Bacher < utz . bacher @ de . ibm . com >
*
* 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 , 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/fs.h>
# include <linux/init.h>
# include <linux/kernel.h>
# include <linux/spinlock.h>
# include <linux/types.h>
# include <asm/machdep.h>
# include <asm/nvram.h>
# include <asm/prom.h>
2005-11-01 04:08:37 +03:00
static void __iomem * mmio_nvram_start ;
static long mmio_nvram_len ;
2006-06-27 13:53:55 +04:00
static DEFINE_SPINLOCK ( mmio_nvram_lock ) ;
2005-06-23 03:43:31 +04:00
2005-11-01 04:08:37 +03:00
static ssize_t mmio_nvram_read ( char * buf , size_t count , loff_t * index )
2005-06-23 03:43:31 +04:00
{
unsigned long flags ;
2005-11-01 04:08:37 +03:00
if ( * index > = mmio_nvram_len )
2005-06-23 03:43:31 +04:00
return 0 ;
2005-11-01 04:08:37 +03:00
if ( * index + count > mmio_nvram_len )
count = mmio_nvram_len - * index ;
2005-06-23 03:43:31 +04:00
2005-11-01 04:08:37 +03:00
spin_lock_irqsave ( & mmio_nvram_lock , flags ) ;
2005-06-23 03:43:31 +04:00
2005-11-01 04:08:37 +03:00
memcpy_fromio ( buf , mmio_nvram_start + * index , count ) ;
2005-06-23 03:43:31 +04:00
2005-11-01 04:08:37 +03:00
spin_unlock_irqrestore ( & mmio_nvram_lock , flags ) ;
2005-06-23 03:43:31 +04:00
* index + = count ;
return count ;
}
2009-07-02 10:12:18 +04:00
static unsigned char mmio_nvram_read_val ( int addr )
{
unsigned long flags ;
unsigned char val ;
if ( addr > = mmio_nvram_len )
return 0xff ;
spin_lock_irqsave ( & mmio_nvram_lock , flags ) ;
val = ioread8 ( mmio_nvram_start + addr ) ;
spin_unlock_irqrestore ( & mmio_nvram_lock , flags ) ;
return val ;
}
2005-11-01 04:08:37 +03:00
static ssize_t mmio_nvram_write ( char * buf , size_t count , loff_t * index )
2005-06-23 03:43:31 +04:00
{
unsigned long flags ;
2005-11-01 04:08:37 +03:00
if ( * index > = mmio_nvram_len )
2005-06-23 03:43:31 +04:00
return 0 ;
2005-11-01 04:08:37 +03:00
if ( * index + count > mmio_nvram_len )
count = mmio_nvram_len - * index ;
2005-06-23 03:43:31 +04:00
2005-11-01 04:08:37 +03:00
spin_lock_irqsave ( & mmio_nvram_lock , flags ) ;
2005-06-23 03:43:31 +04:00
2005-11-01 04:08:37 +03:00
memcpy_toio ( mmio_nvram_start + * index , buf , count ) ;
2005-06-23 03:43:31 +04:00
2005-11-01 04:08:37 +03:00
spin_unlock_irqrestore ( & mmio_nvram_lock , flags ) ;
2005-06-23 03:43:31 +04:00
* index + = count ;
return count ;
}
2016-09-06 08:32:40 +03:00
static void mmio_nvram_write_val ( int addr , unsigned char val )
2009-07-02 10:12:18 +04:00
{
unsigned long flags ;
if ( addr < mmio_nvram_len ) {
spin_lock_irqsave ( & mmio_nvram_lock , flags ) ;
iowrite8 ( val , mmio_nvram_start + addr ) ;
spin_unlock_irqrestore ( & mmio_nvram_lock , flags ) ;
}
}
2005-11-01 04:08:37 +03:00
static ssize_t mmio_nvram_get_size ( void )
2005-06-23 03:43:31 +04:00
{
2005-11-01 04:08:37 +03:00
return mmio_nvram_len ;
2005-06-23 03:43:31 +04:00
}
2005-11-01 04:08:37 +03:00
int __init mmio_nvram_init ( void )
2005-06-23 03:43:31 +04:00
{
struct device_node * nvram_node ;
unsigned long nvram_addr ;
2007-01-11 08:08:41 +03:00
struct resource r ;
2005-06-23 03:43:31 +04:00
int ret ;
nvram_node = of_find_node_by_type ( NULL , " nvram " ) ;
2011-04-15 02:32:00 +04:00
if ( ! nvram_node )
nvram_node = of_find_compatible_node ( NULL , NULL , " nvram " ) ;
2007-01-11 08:08:41 +03:00
if ( ! nvram_node ) {
printk ( KERN_WARNING " nvram: no node found in device-tree \n " ) ;
return - ENODEV ;
}
ret = of_address_to_resource ( nvram_node , 0 , & r ) ;
if ( ret ) {
printk ( KERN_WARNING " nvram: failed to get address (err %d) \n " ,
ret ) ;
2005-06-23 03:43:31 +04:00
goto out ;
2007-01-11 08:08:41 +03:00
}
nvram_addr = r . start ;
2011-06-09 20:13:32 +04:00
mmio_nvram_len = resource_size ( & r ) ;
2007-01-11 08:08:41 +03:00
if ( ( ! mmio_nvram_len ) | | ( ! nvram_addr ) ) {
2007-12-17 22:30:12 +03:00
printk ( KERN_WARNING " nvram: address or length is 0 \n " ) ;
2007-01-11 08:08:41 +03:00
ret = - EIO ;
2005-06-23 03:43:31 +04:00
goto out ;
2007-01-11 08:08:41 +03:00
}
2005-06-23 03:43:31 +04:00
2005-11-01 04:08:37 +03:00
mmio_nvram_start = ioremap ( nvram_addr , mmio_nvram_len ) ;
2007-01-11 08:08:41 +03:00
if ( ! mmio_nvram_start ) {
printk ( KERN_WARNING " nvram: failed to ioremap \n " ) ;
ret = - ENOMEM ;
2005-06-23 03:43:31 +04:00
goto out ;
2007-01-11 08:08:41 +03:00
}
2005-06-23 03:43:31 +04:00
2007-01-11 08:08:41 +03:00
printk ( KERN_INFO " mmio NVRAM, %luk at 0x%lx mapped to %p \n " ,
mmio_nvram_len > > 10 , nvram_addr , mmio_nvram_start ) ;
2005-06-23 03:43:31 +04:00
2009-07-02 10:12:18 +04:00
ppc_md . nvram_read_val = mmio_nvram_read_val ;
ppc_md . nvram_write_val = mmio_nvram_write_val ;
2005-11-01 04:08:37 +03:00
ppc_md . nvram_read = mmio_nvram_read ;
ppc_md . nvram_write = mmio_nvram_write ;
ppc_md . nvram_size = mmio_nvram_get_size ;
2005-06-23 03:43:31 +04:00
out :
of_node_put ( nvram_node ) ;
return ret ;
}