2019-05-27 08:55:01 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2011-09-19 17:45:01 +00:00
/*
* PowerNV nvram code .
*
* Copyright 2011 IBM Corp .
*/
# define DEBUG
2018-04-10 21:49:33 +10:00
# include <linux/delay.h>
2011-09-19 17:45:01 +00:00
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/of.h>
# include <asm/opal.h>
2015-02-06 01:06:52 +05:30
# include <asm/nvram.h>
2011-09-19 17:45:01 +00:00
# include <asm/machdep.h>
static unsigned int nvram_size ;
static ssize_t opal_nvram_size ( void )
{
return nvram_size ;
}
static ssize_t opal_nvram_read ( char * buf , size_t count , loff_t * index )
{
s64 rc ;
int off ;
if ( * index > = nvram_size )
return 0 ;
off = * index ;
if ( ( off + count ) > nvram_size )
count = nvram_size - off ;
rc = opal_read_nvram ( __pa ( buf ) , count , off ) ;
if ( rc ! = OPAL_SUCCESS )
return - EIO ;
* index + = count ;
return count ;
}
2018-05-15 01:59:47 +10:00
/*
* This can be called in the panic path with interrupts off , so use
* mdelay in that case .
*/
2011-09-19 17:45:01 +00:00
static ssize_t opal_nvram_write ( char * buf , size_t count , loff_t * index )
{
s64 rc = OPAL_BUSY ;
int off ;
if ( * index > = nvram_size )
return 0 ;
off = * index ;
if ( ( off + count ) > nvram_size )
count = nvram_size - off ;
while ( rc = = OPAL_BUSY | | rc = = OPAL_BUSY_EVENT ) {
rc = opal_write_nvram ( __pa ( buf ) , count , off ) ;
2018-04-10 21:49:33 +10:00
if ( rc = = OPAL_BUSY_EVENT ) {
2018-05-15 01:59:47 +10:00
if ( in_interrupt ( ) | | irqs_disabled ( ) )
mdelay ( OPAL_BUSY_DELAY_MS ) ;
else
msleep ( OPAL_BUSY_DELAY_MS ) ;
2011-09-19 17:45:01 +00:00
opal_poll_events ( NULL ) ;
2018-04-10 21:49:33 +10:00
} else if ( rc = = OPAL_BUSY ) {
2018-05-15 01:59:47 +10:00
if ( in_interrupt ( ) | | irqs_disabled ( ) )
mdelay ( OPAL_BUSY_DELAY_MS ) ;
else
msleep ( OPAL_BUSY_DELAY_MS ) ;
2018-04-10 21:49:33 +10:00
}
2011-09-19 17:45:01 +00:00
}
2018-03-27 01:02:33 +10:00
if ( rc )
return - EIO ;
2011-09-19 17:45:01 +00:00
* index + = count ;
return count ;
}
2015-02-06 01:06:52 +05:30
static int __init opal_nvram_init_log_partitions ( void )
{
/* Scan nvram for partitions */
nvram_scan_partitions ( ) ;
nvram_init_oops_partition ( 0 ) ;
return 0 ;
}
machine_arch_initcall ( powernv , opal_nvram_init_log_partitions ) ;
2011-09-19 17:45:01 +00:00
void __init opal_nvram_init ( void )
{
struct device_node * np ;
2013-09-23 12:05:00 +10:00
const __be32 * nbytes_p ;
2011-09-19 17:45:01 +00:00
np = of_find_compatible_node ( NULL , NULL , " ibm,opal-nvram " ) ;
if ( np = = NULL )
return ;
nbytes_p = of_get_property ( np , " #bytes " , NULL ) ;
if ( ! nbytes_p ) {
of_node_put ( np ) ;
return ;
}
2013-09-23 12:05:00 +10:00
nvram_size = be32_to_cpup ( nbytes_p ) ;
2011-09-19 17:45:01 +00:00
2014-09-17 14:39:38 +10:00
pr_info ( " OPAL nvram setup, %u bytes \n " , nvram_size ) ;
2011-09-19 17:45:01 +00:00
of_node_put ( np ) ;
ppc_md . nvram_read = opal_nvram_read ;
ppc_md . nvram_write = opal_nvram_write ;
ppc_md . nvram_size = opal_nvram_size ;
}