2005-04-17 02:20:36 +04:00
/*
2013-03-26 00:05:40 +04:00
* This file is subject to the terms and conditions of the GNU General Public
* License . See the file " COPYING " in the main directory of this archive
* for more details .
2005-04-17 02:20:36 +04:00
*
* PROM library initialisation code .
2013-03-26 00:05:40 +04:00
*
* Copyright ( C ) 1999 , 2000 , 2004 , 2005 , 2012 MIPS Technologies , Inc .
* All rights reserved .
* Authors : Carsten Langgaard < carstenl @ mips . com >
* Maciej W . Rozycki < macro @ mips . com >
* Steven J . Hill < sjhill @ mips . com >
2005-04-17 02:20:36 +04:00
*/
# include <linux/init.h>
# include <linux/string.h>
# include <linux/kernel.h>
2013-12-02 20:48:38 +04:00
# include <linux/serial_8250.h>
2005-04-17 02:20:36 +04:00
2005-07-14 19:57:16 +04:00
# include <asm/cacheflush.h>
2011-05-28 18:27:59 +04:00
# include <asm/smp-ops.h>
2005-07-14 19:57:16 +04:00
# include <asm/traps.h>
2013-03-25 23:47:05 +04:00
# include <asm/fw/fw.h>
2014-01-15 14:31:54 +04:00
# include <asm/mips-cm.h>
2014-01-15 14:31:55 +04:00
# include <asm/mips-cpc.h>
2005-04-17 02:20:36 +04:00
# include <asm/mips-boards/generic.h>
# include <asm/mips-boards/malta.h>
2009-03-23 01:12:27 +03:00
static int mips_revision_corid ;
2007-04-27 18:58:41 +04:00
int mips_revision_sconid ;
2005-04-17 02:20:36 +04:00
/* Bonito64 system controller register base. */
unsigned long _pcictrl_bonito ;
unsigned long _pcictrl_bonito_pcicfg ;
/* GT64120 system controller register base */
unsigned long _pcictrl_gt64120 ;
/* MIPS System controller register base */
unsigned long _pcictrl_msc ;
# ifdef CONFIG_SERIAL_8250_CONSOLE
static void __init console_config ( void )
{
char console_string [ 40 ] ;
int baud = 0 ;
char parity = ' \0 ' , bits = ' \0 ' , flow = ' \0 ' ;
char * s ;
2013-12-02 20:48:38 +04:00
s = fw_getenv ( " modetty0 " ) ;
if ( s ) {
while ( * s > = ' 0 ' & & * s < = ' 9 ' )
baud = baud * 10 + * s + + - ' 0 ' ;
if ( * s = = ' , ' )
s + + ;
if ( * s )
parity = * s + + ;
if ( * s = = ' , ' )
s + + ;
if ( * s )
bits = * s + + ;
if ( * s = = ' , ' )
s + + ;
if ( * s = = ' h ' )
2005-04-17 02:20:36 +04:00
flow = ' r ' ;
2013-12-02 20:48:38 +04:00
}
if ( baud = = 0 )
baud = 38400 ;
if ( parity ! = ' n ' & & parity ! = ' o ' & & parity ! = ' e ' )
parity = ' n ' ;
if ( bits ! = ' 7 ' & & bits ! = ' 8 ' )
bits = ' 8 ' ;
if ( flow = = ' \0 ' )
flow = ' r ' ;
if ( ( strstr ( fw_getcmdline ( ) , " earlycon= " ) ) = = NULL ) {
sprintf ( console_string , " uart8250,io,0x3f8,%d%c%c " , baud ,
parity , bits ) ;
setup_early_serial8250_console ( console_string ) ;
}
if ( ( strstr ( fw_getcmdline ( ) , " console= " ) ) = = NULL ) {
2013-03-26 00:05:40 +04:00
sprintf ( console_string , " console=ttyS0,%d%c%c%c " , baud ,
parity , bits , flow ) ;
2013-03-25 23:47:05 +04:00
strcat ( fw_getcmdline ( ) , console_string ) ;
2007-03-01 14:56:43 +03:00
pr_info ( " Config serial console:%s \n " , console_string ) ;
2005-04-17 02:20:36 +04:00
}
}
# endif
2008-04-01 02:03:20 +04:00
static void __init mips_nmi_setup ( void )
2005-07-14 19:57:16 +04:00
{
void * base ;
extern char except_vec_nmi ;
base = cpu_has_veic ?
( void * ) ( CAC_BASE + 0xa80 ) :
( void * ) ( CAC_BASE + 0x380 ) ;
memcpy ( base , & except_vec_nmi , 0x80 ) ;
flush_icache_range ( ( unsigned long ) base , ( unsigned long ) base + 0x80 ) ;
}
2008-04-01 02:03:21 +04:00
static void __init mips_ejtag_setup ( void )
2005-07-14 19:57:16 +04:00
{
void * base ;
extern char except_vec_ejtag_debug ;
base = cpu_has_veic ?
( void * ) ( CAC_BASE + 0xa00 ) :
( void * ) ( CAC_BASE + 0x300 ) ;
memcpy ( base , & except_vec_ejtag_debug , 0x80 ) ;
flush_icache_range ( ( unsigned long ) base , ( unsigned long ) base + 0x80 ) ;
}
2014-01-15 14:31:55 +04:00
phys_t mips_cpc_default_phys_base ( void )
{
return CPC_BASE_ADDR ;
}
2007-11-19 15:23:51 +03:00
extern struct plat_smp_ops msmtc_smp_ops ;
2005-04-17 02:20:36 +04:00
void __init prom_init ( void )
{
mips_display_message ( " LINUX " ) ;
/*
* early setup of _pcictrl_bonito so that we can determine
* the system controller on a CORE_EMUL board
*/
_pcictrl_bonito = ( unsigned long ) ioremap ( BONITO_REG_BASE , BONITO_REG_SIZE ) ;
mips_revision_corid = MIPS_REVISION_CORID ;
if ( mips_revision_corid = = MIPS_REVISION_CORID_CORE_EMUL ) {
2005-09-04 02:56:17 +04:00
if ( BONITO_PCIDID = = 0x0001df53 | |
2005-04-17 02:20:36 +04:00
BONITO_PCIDID = = 0x0003df53 )
mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_BON ;
else
mips_revision_corid = MIPS_REVISION_CORID_CORE_EMUL_MSC ;
}
2007-04-27 18:58:41 +04:00
mips_revision_sconid = MIPS_REVISION_SCONID ;
if ( mips_revision_sconid = = MIPS_REVISION_SCON_OTHER ) {
switch ( mips_revision_corid ) {
case MIPS_REVISION_CORID_QED_RM5261 :
case MIPS_REVISION_CORID_CORE_LV :
case MIPS_REVISION_CORID_CORE_FPGA :
case MIPS_REVISION_CORID_CORE_FPGAR2 :
mips_revision_sconid = MIPS_REVISION_SCON_GT64120 ;
break ;
case MIPS_REVISION_CORID_CORE_EMUL_BON :
case MIPS_REVISION_CORID_BONITO64 :
case MIPS_REVISION_CORID_CORE_20K :
mips_revision_sconid = MIPS_REVISION_SCON_BONITO ;
break ;
case MIPS_REVISION_CORID_CORE_MSC :
case MIPS_REVISION_CORID_CORE_FPGA2 :
case MIPS_REVISION_CORID_CORE_24K :
2007-09-21 17:50:08 +04:00
/*
* SOCit / ROCit support is essentially identical
* but make an attempt to distinguish them
*/
2007-04-27 18:58:41 +04:00
mips_revision_sconid = MIPS_REVISION_SCON_SOCIT ;
break ;
2007-09-21 17:50:08 +04:00
case MIPS_REVISION_CORID_CORE_FPGA3 :
case MIPS_REVISION_CORID_CORE_FPGA4 :
case MIPS_REVISION_CORID_CORE_FPGA5 :
case MIPS_REVISION_CORID_CORE_EMUL_MSC :
2007-04-27 18:58:41 +04:00
default :
2007-09-21 17:50:08 +04:00
/* See above */
mips_revision_sconid = MIPS_REVISION_SCON_ROCIT ;
break ;
2007-04-27 18:58:41 +04:00
}
}
switch ( mips_revision_sconid ) {
2007-03-04 20:26:56 +03:00
u32 start , map , mask , data ;
2007-04-27 18:58:41 +04:00
case MIPS_REVISION_SCON_GT64120 :
2005-04-17 02:20:36 +04:00
/*
* Setup the North bridge to do Master byte - lane swapping
* when running in bigendian .
*/
_pcictrl_gt64120 = ( unsigned long ) ioremap ( MIPS_GT_BASE , 0x2000 ) ;
# ifdef CONFIG_CPU_LITTLE_ENDIAN
GT_WRITE ( GT_PCI0_CMD_OFS , GT_PCI0_CMD_MBYTESWAP_BIT |
GT_PCI0_CMD_SBYTESWAP_BIT ) ;
# else
GT_WRITE ( GT_PCI0_CMD_OFS , 0 ) ;
# endif
2005-02-01 23:18:59 +03:00
/* Fix up PCI I/O mapping if necessary (for Atlas). */
start = GT_READ ( GT_PCI0IOLD_OFS ) ;
map = GT_READ ( GT_PCI0IOREMAP_OFS ) ;
if ( ( start & map ) ! = 0 ) {
map & = ~ start ;
GT_WRITE ( GT_PCI0IOREMAP_OFS , map ) ;
}
2005-04-17 02:20:36 +04:00
set_io_port_base ( MALTA_GT_PORT_BASE ) ;
break ;
2007-04-27 18:58:41 +04:00
case MIPS_REVISION_SCON_BONITO :
2005-04-17 02:20:36 +04:00
_pcictrl_bonito_pcicfg = ( unsigned long ) ioremap ( BONITO_PCICFG_BASE , BONITO_PCICFG_SIZE ) ;
/*
* Disable Bonito IOBC .
*/
BONITO_PCIMEMBASECFG = BONITO_PCIMEMBASECFG &
~ ( BONITO_PCIMEMBASECFG_MEMBASE0_CACHED |
BONITO_PCIMEMBASECFG_MEMBASE1_CACHED ) ;
/*
* Setup the North bridge to do Master byte - lane swapping
* when running in bigendian .
*/
# ifdef CONFIG_CPU_LITTLE_ENDIAN
BONITO_BONGENCFG = BONITO_BONGENCFG &
~ ( BONITO_BONGENCFG_MSTRBYTESWAP |
BONITO_BONGENCFG_BYTESWAP ) ;
# else
BONITO_BONGENCFG = BONITO_BONGENCFG |
BONITO_BONGENCFG_MSTRBYTESWAP |
BONITO_BONGENCFG_BYTESWAP ;
# endif
set_io_port_base ( MALTA_BONITO_PORT_BASE ) ;
break ;
2007-04-27 18:58:41 +04:00
case MIPS_REVISION_SCON_SOCIT :
case MIPS_REVISION_SCON_ROCIT :
2005-09-04 02:56:17 +04:00
_pcictrl_msc = ( unsigned long ) ioremap ( MIPS_MSC01_PCI_REG_BASE , 0x2000 ) ;
2013-03-26 00:05:40 +04:00
mips_pci_controller :
2005-02-01 23:18:59 +03:00
mb ( ) ;
MSC_READ ( MSC01_PCI_CFG , data ) ;
MSC_WRITE ( MSC01_PCI_CFG , data & ~ MSC01_PCI_CFG_EN_BIT ) ;
wmb ( ) ;
/* Fix up lane swapping. */
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_CPU_LITTLE_ENDIAN
MSC_WRITE ( MSC01_PCI_SWAP , MSC01_PCI_SWAP_NOSWAP ) ;
# else
MSC_WRITE ( MSC01_PCI_SWAP ,
MSC01_PCI_SWAP_BYTESWAP < < MSC01_PCI_SWAP_IO_SHF |
MSC01_PCI_SWAP_BYTESWAP < < MSC01_PCI_SWAP_MEM_SHF |
MSC01_PCI_SWAP_BYTESWAP < < MSC01_PCI_SWAP_BAR0_SHF ) ;
# endif
2014-01-17 17:11:29 +04:00
# ifndef CONFIG_EVA
2005-02-01 23:18:59 +03:00
/* Fix up target memory mapping. */
MSC_READ ( MSC01_PCI_BAR0 , mask ) ;
MSC_WRITE ( MSC01_PCI_P2SCMSKL , mask & MSC01_PCI_BAR0_SIZE_MSK ) ;
2014-01-17 17:11:29 +04:00
# else
/*
* Setup the Malta max ( 2 GB ) memory for PCI DMA in host bridge
* in transparent addressing mode , starting from 0x80000000 .
*/
mask = PHYS_OFFSET | ( 1 < < 3 ) ;
MSC_WRITE ( MSC01_PCI_BAR0 , mask ) ;
2005-02-01 23:18:59 +03:00
2014-01-17 17:11:29 +04:00
mask = PHYS_OFFSET ;
MSC_WRITE ( MSC01_PCI_HEAD4 , mask ) ;
MSC_WRITE ( MSC01_PCI_P2SCMSKL , mask ) ;
MSC_WRITE ( MSC01_PCI_P2SCMAPL , mask ) ;
# endif
2005-02-01 23:18:59 +03:00
/* Don't handle target retries indefinitely. */
if ( ( data & MSC01_PCI_CFG_MAXRTRY_MSK ) = =
MSC01_PCI_CFG_MAXRTRY_MSK )
data = ( data & ~ ( MSC01_PCI_CFG_MAXRTRY_MSK < <
MSC01_PCI_CFG_MAXRTRY_SHF ) ) |
( ( MSC01_PCI_CFG_MAXRTRY_MSK - 1 ) < <
MSC01_PCI_CFG_MAXRTRY_SHF ) ;
wmb ( ) ;
MSC_WRITE ( MSC01_PCI_CFG , data ) ;
mb ( ) ;
2005-04-17 02:20:36 +04:00
set_io_port_base ( MALTA_MSC_PORT_BASE ) ;
break ;
2007-04-27 18:58:41 +04:00
case MIPS_REVISION_SCON_SOCITSC :
case MIPS_REVISION_SCON_SOCITSCP :
_pcictrl_msc = ( unsigned long ) ioremap ( MIPS_SOCITSC_PCI_REG_BASE , 0x2000 ) ;
goto mips_pci_controller ;
2005-04-17 02:20:36 +04:00
default :
2007-04-27 18:58:41 +04:00
/* Unknown system controller */
mips_display_message ( " SC Error " ) ;
2013-03-26 00:05:40 +04:00
while ( 1 ) ; /* We die here... */
2005-04-17 02:20:36 +04:00
}
2005-07-14 19:57:16 +04:00
board_nmi_handler_setup = mips_nmi_setup ;
board_ejtag_handler_setup = mips_ejtag_setup ;
2013-03-25 23:47:05 +04:00
fw_init_cmdline ( ) ;
fw_meminit ( ) ;
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_SERIAL_8250_CONSOLE
console_config ( ) ;
# endif
2011-03-29 13:43:19 +04:00
/* Early detection of CMP support */
2014-01-15 14:31:54 +04:00
mips_cm_probe ( ) ;
2014-01-15 14:31:55 +04:00
mips_cpc_probe ( ) ;
2011-05-28 18:27:59 +04:00
2014-01-15 14:31:56 +04:00
if ( ! register_cps_smp_ops ( ) )
return ;
2014-01-15 14:31:54 +04:00
if ( ! register_cmp_smp_ops ( ) )
return ;
2011-05-28 18:27:59 +04:00
if ( ! register_vsmp_smp_ops ( ) )
return ;
2007-11-19 15:23:51 +03:00
# ifdef CONFIG_MIPS_MT_SMTC
register_smp_ops ( & msmtc_smp_ops ) ;
# endif
2005-04-17 02:20:36 +04:00
}