2005-06-23 09:43:37 +10:00
/*
2005-10-31 20:08:37 -05:00
* linux / arch / powerpc / platforms / cell / cell_setup . c
2005-06-23 09:43:37 +10:00
*
* Copyright ( C ) 1995 Linus Torvalds
* Adapted from ' alpha ' version by Gary Thomas
* Modified by Cort Dougan ( cort @ cs . nmt . edu )
* Modified by PPC64 Team , IBM Corp
2005-10-31 20:08:37 -05:00
* Modified by Cell Team , IBM Deutschland Entwicklung GmbH
2005-06-23 09:43:37 +10:00
*
* 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/sched.h>
# include <linux/kernel.h>
# include <linux/mm.h>
# include <linux/stddef.h>
2011-05-27 10:46:24 -04:00
# include <linux/export.h>
2005-06-23 09:43:37 +10:00
# include <linux/unistd.h>
# include <linux/user.h>
# include <linux/reboot.h>
# include <linux/init.h>
# include <linux/delay.h>
# include <linux/irq.h>
# include <linux/seq_file.h>
# include <linux/root_dev.h>
# include <linux/console.h>
2006-05-01 12:16:11 -07:00
# include <linux/mutex.h>
# include <linux/memory_hotplug.h>
2007-11-13 11:10:58 -06:00
# include <linux/of_platform.h>
2005-06-23 09:43:37 +10:00
# include <asm/mmu.h>
# include <asm/processor.h>
# include <asm/io.h>
# include <asm/pgtable.h>
# include <asm/prom.h>
# include <asm/rtas.h>
# include <asm/pci-bridge.h>
# include <asm/iommu.h>
# include <asm/dma.h>
# include <asm/machdep.h>
# include <asm/time.h>
# include <asm/nvram.h>
# include <asm/cputable.h>
2005-09-28 02:50:25 +10:00
# include <asm/ppc-pci.h>
2005-10-10 22:50:37 +10:00
# include <asm/irq.h>
2006-05-01 12:16:11 -07:00
# include <asm/spu.h>
2006-06-19 20:33:29 +02:00
# include <asm/spu_priv1.h>
2006-06-29 16:52:53 -04:00
# include <asm/udbg.h>
2006-11-11 17:24:58 +11:00
# include <asm/mpic.h>
2007-10-04 15:40:42 +10:00
# include <asm/cell-regs.h>
2011-04-11 21:25:01 +00:00
# include <asm/io-workarounds.h>
2005-06-23 09:43:37 +10:00
2015-03-31 16:00:55 +11:00
# include "cell.h"
2005-10-31 20:08:37 -05:00
# include "interrupt.h"
2006-01-04 19:55:53 +00:00
# include "pervasive.h"
2006-06-19 20:33:16 +02:00
# include "ras.h"
2005-06-23 09:43:37 +10:00
# ifdef DEBUG
# define DBG(fmt...) udbg_printf(fmt)
# else
# define DBG(fmt...)
# endif
2006-01-11 23:07:11 +00:00
static void cell_show_cpuinfo ( struct seq_file * m )
2005-06-23 09:43:37 +10:00
{
struct device_node * root ;
const char * model = " " ;
root = of_find_node_by_path ( " / " ) ;
if ( root )
2007-04-03 22:26:41 +10:00
model = of_get_property ( root , " model " , NULL ) ;
2005-10-31 20:08:37 -05:00
seq_printf ( m , " machine \t \t : CHRP %s \n " , model ) ;
2005-06-23 09:43:37 +10:00
of_node_put ( root ) ;
}
2005-10-31 20:08:37 -05:00
static void cell_progress ( char * s , unsigned short hex )
2005-06-23 09:43:37 +10:00
{
printk ( " *** %04x : %s \n " , hex , s ? s : " " ) ;
}
2008-03-19 17:10:55 +11:00
static void cell_fixup_pcie_rootcomplex ( struct pci_dev * dev )
{
struct pci_controller * hose ;
const char * s ;
int i ;
if ( ! machine_is ( cell ) )
return ;
/* We're searching for a direct child of the PHB */
if ( dev - > bus - > self ! = NULL | | dev - > devfn ! = 0 )
return ;
hose = pci_bus_to_host ( dev - > bus ) ;
if ( hose = = NULL )
return ;
/* Only on PCIE */
if ( ! of_device_is_compatible ( hose - > dn , " pciex " ) )
return ;
/* And only on axon */
s = of_get_property ( hose - > dn , " model " , NULL ) ;
if ( ! s | | strcmp ( s , " Axon " ) ! = 0 )
return ;
for ( i = 0 ; i < PCI_BRIDGE_RESOURCES ; i + + ) {
dev - > resource [ i ] . start = dev - > resource [ i ] . end = 0 ;
dev - > resource [ i ] . flags = 0 ;
}
printk ( KERN_DEBUG " PCI: Hiding resources on Axon PCIE RC %s \n " ,
pci_name ( dev ) ) ;
}
DECLARE_PCI_FIXUP_HEADER ( PCI_ANY_ID , PCI_ANY_ID , cell_fixup_pcie_rootcomplex ) ;
2012-12-21 14:04:10 -08:00
static int cell_setup_phb ( struct pci_controller * phb )
2008-04-24 19:21:10 +10:00
{
const char * model ;
struct device_node * np ;
int rc = rtas_setup_phb ( phb ) ;
if ( rc )
return rc ;
2015-04-14 16:49:06 +10:00
phb - > controller_ops = cell_pci_controller_ops ;
2008-04-24 19:21:10 +10:00
np = phb - > dn ;
model = of_get_property ( np , " model " , NULL ) ;
if ( model = = NULL | | strcmp ( np - > name , " pci " ) )
return 0 ;
/* Setup workarounds for spider */
if ( strcmp ( model , " Spider " ) )
return 0 ;
iowa_register_bus ( phb , & spiderpci_ops , & spiderpci_iowa_init ,
( void * ) SPIDER_PCI_REG_BASE ) ;
return 0 ;
}
2012-03-30 10:05:00 +00:00
static const struct of_device_id cell_bus_ids [ ] __initconst = {
2010-07-23 20:19:24 +02:00
{ . type = " soc " , } ,
{ . compatible = " soc " , } ,
{ . type = " spider " , } ,
{ . type = " axon " , } ,
{ . type = " plb5 " , } ,
{ . type = " plb4 " , } ,
{ . type = " opb " , } ,
{ . type = " ebc " , } ,
{ } ,
} ;
2006-11-11 17:25:00 +11:00
static int __init cell_publish_devices ( void )
{
2008-04-24 19:21:10 +10:00
struct device_node * root = of_find_node_by_path ( " / " ) ;
struct device_node * np ;
2007-10-04 15:40:43 +10:00
int node ;
2006-11-11 17:25:04 +11:00
/* Publish OF platform devices for southbridge IOs */
2010-07-23 20:19:24 +02:00
of_platform_bus_probe ( NULL , cell_bus_ids , NULL ) ;
2006-11-11 17:25:04 +11:00
2008-04-24 19:21:10 +10:00
/* On spider based blades, we need to manually create the OF
* platform devices for the PCI host bridges
*/
for_each_child_of_node ( root , np ) {
if ( np - > type = = NULL | | ( strcmp ( np - > type , " pci " ) ! = 0 & &
strcmp ( np - > type , " pciex " ) ! = 0 ) )
continue ;
of_platform_device_create ( np , NULL , NULL ) ;
}
2007-10-04 15:40:43 +10:00
/* There is no device for the MIC memory controller, thus we create
* a platform device for it to attach the EDAC driver to .
*/
for_each_online_node ( node ) {
if ( cbe_get_cpu_mic_tm_regs ( cbe_node_to_cpu ( node ) ) = = NULL )
continue ;
platform_device_register_simple ( " cbe-mic " , node , NULL , 0 ) ;
}
2008-04-24 19:21:10 +10:00
2006-11-11 17:25:00 +11:00
return 0 ;
}
2008-01-25 16:59:12 +11:00
machine_subsys_initcall ( cell , cell_publish_devices ) ;
2006-11-11 17:25:00 +11:00
2006-11-11 17:24:58 +11:00
static void __init mpic_init_IRQ ( void )
{
struct device_node * dn ;
struct mpic * mpic ;
for ( dn = NULL ;
( dn = of_find_node_by_name ( dn , " interrupt-controller " ) ) ; ) {
2007-05-03 17:26:52 +10:00
if ( ! of_device_is_compatible ( dn , " CBEA,platform-open-pic " ) )
2006-11-11 17:24:58 +11:00
continue ;
/* The MPIC driver will get everything it needs from the
* device - tree , just pass 0 to all arguments
*/
2011-12-22 10:19:14 +00:00
mpic = mpic_alloc ( dn , 0 , MPIC_SECONDARY | MPIC_NO_RESET ,
0 , 0 , " MPIC " ) ;
2006-11-11 17:24:58 +11:00
if ( mpic = = NULL )
continue ;
mpic_init ( mpic ) ;
}
}
2006-07-03 19:32:51 +10:00
static void __init cell_init_irq ( void )
{
iic_init_IRQ ( ) ;
spider_init_IRQ ( ) ;
2006-11-11 17:24:58 +11:00
mpic_init_IRQ ( ) ;
2006-07-03 19:32:51 +10:00
}
2008-02-28 11:27:31 +01:00
static void __init cell_set_dabrx ( void )
{
mtspr ( SPRN_DABRX , DABRX_KERNEL | DABRX_USER ) ;
}
2005-10-31 20:08:37 -05:00
static void __init cell_setup_arch ( void )
2005-06-23 09:43:37 +10:00
{
2006-06-19 20:33:29 +02:00
# ifdef CONFIG_SPU_BASE
2006-11-23 00:46:49 +01:00
spu_priv1_ops = & spu_priv1_mmio_ops ;
spu_management_ops = & spu_management_of_ops ;
2006-06-19 20:33:29 +02:00
# endif
2005-06-23 09:43:43 +10:00
2006-06-19 20:33:16 +02:00
cbe_regs_init ( ) ;
2008-02-28 11:27:31 +01:00
cell_set_dabrx ( ) ;
2006-06-19 20:33:16 +02:00
# ifdef CONFIG_CBE_RAS
cbe_ras_init ( ) ;
# endif
2005-06-23 09:43:37 +10:00
# ifdef CONFIG_SMP
2005-10-31 20:08:37 -05:00
smp_init_cell ( ) ;
2005-06-23 09:43:37 +10:00
# endif
/* init to some ~sane value until calibrate_delay() runs */
loops_per_jiffy = 50000000 ;
/* Find and initialize PCI host bridges */
init_pci_config_tokens ( ) ;
2008-04-24 19:21:10 +10:00
2006-06-19 20:33:16 +02:00
cbe_pervasive_init ( ) ;
2005-06-23 09:43:37 +10:00
# ifdef CONFIG_DUMMY_CONSOLE
conswitchp = & dummy_con ;
# endif
2005-10-31 20:08:37 -05:00
mmio_nvram_init ( ) ;
2005-06-23 09:43:37 +10:00
}
2006-03-28 23:15:54 +11:00
static int __init cell_probe ( void )
2005-06-23 09:43:37 +10:00
{
2006-03-28 23:15:54 +11:00
unsigned long root = of_get_flat_dt_root ( ) ;
2005-06-23 09:43:37 +10:00
2006-06-23 18:16:38 +10:00
if ( ! of_flat_dt_is_compatible ( root , " IBM,CBEA " ) & &
! of_flat_dt_is_compatible ( root , " IBM,CPBW-1.0 " ) )
return 0 ;
hpte_init_native ( ) ;
2014-10-13 16:01:09 +02:00
pm_power_off = rtas_power_off ;
2006-06-07 12:04:18 +10:00
2006-06-23 18:16:38 +10:00
return 1 ;
2005-06-23 09:43:37 +10:00
}
2006-03-28 23:15:54 +11:00
define_machine ( cell ) {
. name = " Cell " ,
2005-10-31 20:08:37 -05:00
. probe = cell_probe ,
. setup_arch = cell_setup_arch ,
. show_cpuinfo = cell_show_cpuinfo ,
2005-06-23 09:43:37 +10:00
. restart = rtas_restart ,
. halt = rtas_halt ,
. get_boot_time = rtas_get_boot_time ,
. get_rtc_time = rtas_get_rtc_time ,
. set_rtc_time = rtas_set_rtc_time ,
. calibrate_decr = generic_calibrate_decr ,
2005-10-31 20:08:37 -05:00
. progress = cell_progress ,
2006-07-03 19:32:51 +10:00
. init_IRQ = cell_init_irq ,
2008-04-24 19:21:10 +10:00
. pci_setup_phb = cell_setup_phb ,
2005-06-23 09:43:37 +10:00
} ;
2015-03-31 16:00:55 +11:00
struct pci_controller_ops cell_pci_controller_ops ;