2011-09-19 17:44:52 +00:00
/*
* PowerNV setup code .
*
* Copyright 2011 IBM Corp .
*
* 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 .
*/
# undef DEBUG
# include <linux/cpu.h>
# include <linux/errno.h>
# include <linux/sched.h>
# include <linux/kernel.h>
# include <linux/tty.h>
# include <linux/reboot.h>
# include <linux/init.h>
# include <linux/console.h>
# include <linux/delay.h>
# include <linux/irq.h>
# include <linux/seq_file.h>
# include <linux/of.h>
2013-09-26 07:40:04 -05:00
# include <linux/of_fdt.h>
2011-09-19 17:44:52 +00:00
# include <linux/interrupt.h>
# include <linux/bug.h>
2014-02-11 11:32:38 +11:00
# include <linux/pci.h>
2014-03-11 17:01:19 +05:30
# include <linux/cpufreq.h>
2011-09-19 17:44:52 +00:00
# include <asm/machdep.h>
# include <asm/firmware.h>
# include <asm/xics.h>
2017-04-05 17:54:50 +10:00
# include <asm/xive.h>
2011-09-19 17:44:59 +00:00
# include <asm/opal.h>
2013-08-21 13:03:20 +10:00
# include <asm/kexec.h>
2014-06-06 15:51:05 +05:30
# include <asm/smp.h>
2011-09-19 17:44:52 +00:00
# include "powernv.h"
static void __init pnv_setup_arch ( void )
{
2014-05-01 07:20:04 +10:00
set_arch_panic_timeout ( 10 , ARCH_PANIC_TIMEOUT ) ;
2011-09-19 17:44:52 +00:00
/* Initialize SMP */
pnv_smp_init ( ) ;
2011-09-19 17:45:05 +00:00
/* Setup PCI */
pnv_pci_init ( ) ;
2011-09-19 17:44:52 +00:00
2011-09-19 17:45:01 +00:00
/* Setup RTC and NVRAM callbacks */
if ( firmware_has_feature ( FW_FEATURE_OPAL ) )
opal_nvram_init ( ) ;
2011-09-19 17:44:52 +00:00
/* Enable NAP mode */
powersave_nap = 1 ;
/* XXX PMCS */
}
2016-07-05 15:04:06 +10:00
static void __init pnv_init ( void )
2011-09-19 17:44:52 +00:00
{
2013-07-15 13:03:11 +10:00
/*
* Initialize the LPC bus now so that legacy serial
* ports can be found on it
*/
opal_lpc_init ( ) ;
2011-09-19 17:44:59 +00:00
# ifdef CONFIG_HVC_OPAL
if ( firmware_has_feature ( FW_FEATURE_OPAL ) )
hvc_opal_init_early ( ) ;
else
# endif
add_preferred_console ( " hvc " , 0 , NULL ) ;
2011-09-19 17:44:52 +00:00
}
static void __init pnv_init_IRQ ( void )
{
2017-04-05 17:54:50 +10:00
/* Try using a XIVE if available, otherwise use a XICS */
if ( ! xive_native_init ( ) )
xics_init ( ) ;
2011-09-19 17:44:52 +00:00
WARN_ON ( ! ppc_md . get_irq ) ;
}
static void pnv_show_cpuinfo ( struct seq_file * m )
{
struct device_node * root ;
const char * model = " " ;
root = of_find_node_by_path ( " / " ) ;
if ( root )
model = of_get_property ( root , " model " , NULL ) ;
seq_printf ( m , " machine \t \t : PowerNV %s \n " , model ) ;
2015-12-09 17:18:20 +11:00
if ( firmware_has_feature ( FW_FEATURE_OPAL ) )
seq_printf ( m , " firmware \t : OPAL \n " ) ;
2011-09-19 17:44:57 +00:00
else
seq_printf ( m , " firmware \t : BML \n " ) ;
2011-09-19 17:44:52 +00:00
of_node_put ( root ) ;
2017-03-21 22:59:55 +05:30
if ( radix_enabled ( ) )
seq_printf ( m , " MMU \t \t : Radix \n " ) ;
else
seq_printf ( m , " MMU \t \t : Hash \n " ) ;
2011-09-19 17:44:52 +00:00
}
2014-04-09 22:48:55 +05:30
static void pnv_prepare_going_down ( void )
{
/*
* Disable all notifiers from OPAL , we can ' t
* service interrupts anymore anyway
*/
2015-05-15 14:06:44 +10:00
opal_event_shutdown ( ) ;
2014-04-09 22:48:55 +05:30
/* Soft disable interrupts */
local_irq_disable ( ) ;
/*
* Return secondary CPUs to firwmare if a flash update
* is pending otherwise we will get all sort of error
* messages about CPU being stuck etc . . This will also
* have the side effect of hard disabling interrupts so
* past this point , the kernel is effectively dead .
*/
opal_flash_term_callback ( ) ;
}
2011-09-19 18:28:03 +00:00
static void __noreturn pnv_restart ( char * cmd )
2011-09-19 17:44:52 +00:00
{
2011-09-19 18:28:03 +00:00
long rc = OPAL_BUSY ;
2014-04-09 22:48:55 +05:30
pnv_prepare_going_down ( ) ;
2013-06-20 18:13:23 +08:00
2011-09-19 18:28:03 +00:00
while ( rc = = OPAL_BUSY | | rc = = OPAL_BUSY_EVENT ) {
rc = opal_cec_reboot ( ) ;
if ( rc = = OPAL_BUSY_EVENT )
opal_poll_events ( NULL ) ;
else
mdelay ( 10 ) ;
}
for ( ; ; )
opal_poll_events ( NULL ) ;
2011-09-19 17:44:52 +00:00
}
2011-09-19 18:28:03 +00:00
static void __noreturn pnv_power_off ( void )
2011-09-19 17:44:52 +00:00
{
2011-09-19 18:28:03 +00:00
long rc = OPAL_BUSY ;
2014-04-09 22:48:55 +05:30
pnv_prepare_going_down ( ) ;
2013-06-20 18:13:23 +08:00
2011-09-19 18:28:03 +00:00
while ( rc = = OPAL_BUSY | | rc = = OPAL_BUSY_EVENT ) {
rc = opal_cec_power_down ( 0 ) ;
if ( rc = = OPAL_BUSY_EVENT )
opal_poll_events ( NULL ) ;
else
mdelay ( 10 ) ;
}
for ( ; ; )
opal_poll_events ( NULL ) ;
2011-09-19 17:44:52 +00:00
}
2011-09-19 18:28:03 +00:00
static void __noreturn pnv_halt ( void )
2011-09-19 17:44:52 +00:00
{
2011-09-19 18:28:03 +00:00
pnv_power_off ( ) ;
2011-09-19 17:44:52 +00:00
}
2011-09-19 17:45:01 +00:00
static void pnv_progress ( char * s , unsigned short hex )
2011-09-19 17:44:52 +00:00
{
}
2013-05-10 16:59:18 +10:00
static void pnv_shutdown ( void )
{
/* Let the PCI code clear up IODA tables */
pnv_pci_shutdown ( ) ;
2014-01-15 17:02:04 +11:00
/*
* Stop OPAL activity : Unregister all OPAL interrupts so they
* don ' t fire up while we kexec and make sure all potentially
* DMA ' ing ops are complete ( such as dump retrieval ) .
2013-05-10 16:59:18 +10:00
*/
opal_shutdown ( ) ;
}
2016-11-29 23:45:50 +11:00
# ifdef CONFIG_KEXEC_CORE
2014-04-24 16:14:25 +10:00
static void pnv_kexec_wait_secondaries_down ( void )
{
int my_cpu , i , notified = - 1 ;
my_cpu = get_cpu ( ) ;
for_each_online_cpu ( i ) {
uint8_t status ;
2015-07-22 15:54:29 +10:00
int64_t rc , timeout = 1000 ;
2014-04-24 16:14:25 +10:00
if ( i = = my_cpu )
continue ;
for ( ; ; ) {
rc = opal_query_cpu_status ( get_hard_smp_processor_id ( i ) ,
& status ) ;
if ( rc ! = OPAL_SUCCESS | | status ! = OPAL_THREAD_STARTED )
break ;
barrier ( ) ;
if ( i ! = notified ) {
printk ( KERN_INFO " kexec: waiting for cpu %d "
" (physical %d) to enter OPAL \n " ,
i , paca [ i ] . hw_cpu_id ) ;
notified = i ;
}
2015-07-22 15:54:29 +10:00
/*
* On crash secondaries might be unreachable or hung ,
* so timeout if we ' ve waited too long
* */
mdelay ( 1 ) ;
if ( timeout - - = = 0 ) {
printk ( KERN_ERR " kexec: timed out waiting for "
" cpu %d (physical %d) to enter OPAL \n " ,
i , paca [ i ] . hw_cpu_id ) ;
break ;
}
2014-04-24 16:14:25 +10:00
}
}
}
2011-09-19 17:45:01 +00:00
static void pnv_kexec_cpu_down ( int crash_shutdown , int secondary )
2011-09-19 17:44:52 +00:00
{
2017-06-30 17:37:32 -05:00
u64 reinit_flags ;
2017-04-05 17:54:50 +10:00
if ( xive_enabled ( ) )
xive_kexec_teardown_cpu ( secondary ) ;
else
xics_kexec_teardown_cpu ( secondary ) ;
2013-08-21 13:03:20 +10:00
2015-12-09 17:18:20 +11:00
/* On OPAL, we return all CPUs to firmware */
if ( ! firmware_has_feature ( FW_FEATURE_OPAL ) )
2014-04-24 16:14:25 +10:00
return ;
if ( secondary ) {
/* Return secondary CPUs to firmware on OPAL v3 */
2013-08-21 13:03:20 +10:00
mb ( ) ;
get_paca ( ) - > kexec_state = KEXEC_STATE_REAL_MODE ;
mb ( ) ;
/* Return the CPU to OPAL */
opal_return_cpu ( ) ;
2014-04-24 16:14:25 +10:00
} else {
/* Primary waits for the secondaries to have reached OPAL */
pnv_kexec_wait_secondaries_down ( ) ;
2015-07-22 15:50:51 +10:00
2017-04-05 17:54:50 +10:00
/* Switch XIVE back to emulation mode */
if ( xive_enabled ( ) )
xive_shutdown ( ) ;
2015-07-22 15:50:51 +10:00
/*
* We might be running as little - endian - now that interrupts
* are disabled , reset the HILE bit to big - endian so we don ' t
* take interrupts in the wrong endian later
2017-06-30 17:37:32 -05:00
*
* We reinit to enable both radix and hash on P9 to ensure
* the mode used by the next kernel is always supported .
2015-07-22 15:50:51 +10:00
*/
2017-06-30 17:37:32 -05:00
reinit_flags = OPAL_REINIT_CPUS_HILE_BE ;
if ( cpu_has_feature ( CPU_FTR_ARCH_300 ) )
reinit_flags | = OPAL_REINIT_CPUS_MMU_RADIX |
OPAL_REINIT_CPUS_MMU_HASH ;
opal_reinit_cpus ( reinit_flags ) ;
2013-08-21 13:03:20 +10:00
}
2011-09-19 17:44:52 +00:00
}
2016-11-29 23:45:50 +11:00
# endif /* CONFIG_KEXEC_CORE */
2011-09-19 17:44:52 +00:00
2014-06-04 17:52:42 +10:00
# ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
static unsigned long pnv_memory_block_size ( void )
{
return 256UL * 1024 * 1024 ;
}
# endif
2011-09-19 17:45:01 +00:00
static void __init pnv_setup_machdep_opal ( void )
2011-09-19 17:44:52 +00:00
{
2011-09-19 17:45:01 +00:00
ppc_md . get_boot_time = opal_get_boot_time ;
ppc_md . restart = pnv_restart ;
2014-10-13 16:01:09 +02:00
pm_power_off = pnv_power_off ;
2011-09-19 17:45:01 +00:00
ppc_md . halt = pnv_halt ;
2011-09-19 17:45:04 +00:00
ppc_md . machine_check_exception = opal_machine_check ;
2013-12-16 10:46:24 +05:30
ppc_md . mce_check_early_recovery = opal_mce_check_early_recovery ;
2014-07-29 18:40:01 +05:30
ppc_md . hmi_exception_early = opal_hmi_exception_early ;
ppc_md . handle_hmi_exception = opal_handle_hmi_exception ;
2011-09-19 17:44:52 +00:00
}
static int __init pnv_probe ( void )
{
2016-07-05 15:04:00 +10:00
if ( ! of_machine_is_compatible ( " ibm,powernv " ) )
2011-09-19 17:44:52 +00:00
return 0 ;
2011-09-19 17:45:01 +00:00
if ( firmware_has_feature ( FW_FEATURE_OPAL ) )
pnv_setup_machdep_opal ( ) ;
2011-09-19 17:44:52 +00:00
pr_debug ( " PowerNV detected ! \n " ) ;
2016-07-05 15:04:06 +10:00
pnv_init ( ) ;
2011-09-19 17:44:52 +00:00
return 1 ;
}
2014-03-11 17:01:19 +05:30
/*
* Returns the cpu frequency for ' cpu ' in Hz . This is used by
* / proc / cpuinfo
*/
2014-08-20 08:55:18 +10:00
static unsigned long pnv_get_proc_freq ( unsigned int cpu )
2014-03-11 17:01:19 +05:30
{
unsigned long ret_freq ;
ret_freq = cpufreq_quick_get ( cpu ) * 1000ul ;
/*
* If the backend cpufreq driver does not exist ,
* then fallback to old way of reporting the clockrate .
*/
if ( ! ret_freq )
ret_freq = ppc_proc_freq ;
return ret_freq ;
}
2011-09-19 17:44:52 +00:00
define_machine ( powernv ) {
. name = " PowerNV " ,
. probe = pnv_probe ,
2011-09-19 17:45:01 +00:00
. setup_arch = pnv_setup_arch ,
2011-09-19 17:44:52 +00:00
. init_IRQ = pnv_init_IRQ ,
. show_cpuinfo = pnv_show_cpuinfo ,
2014-03-11 17:01:19 +05:30
. get_proc_freq = pnv_get_proc_freq ,
2011-09-19 17:44:52 +00:00
. progress = pnv_progress ,
2013-05-10 16:59:18 +10:00
. machine_shutdown = pnv_shutdown ,
2016-06-08 11:54:27 -05:00
. power_save = NULL ,
2011-09-19 17:44:52 +00:00
. calibrate_decr = generic_calibrate_decr ,
2016-11-29 23:45:50 +11:00
# ifdef CONFIG_KEXEC_CORE
2011-09-19 17:44:52 +00:00
. kexec_cpu_down = pnv_kexec_cpu_down ,
# endif
2014-06-04 17:52:42 +10:00
# ifdef CONFIG_MEMORY_HOTPLUG_SPARSE
. memory_block_size = pnv_memory_block_size ,
# endif
2011-09-19 17:44:52 +00:00
} ;