2006-01-14 16:57:39 -06:00
/*
* MPC85xx setup and early boot code plus other random bits .
*
* Maintained by Kumar Gala ( see MAINTAINERS for contact information )
*
* Copyright 2005 Freescale Semiconductor Inc .
*
* 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 .
*/
# include <linux/stddef.h>
# include <linux/kernel.h>
# include <linux/pci.h>
# include <linux/kdev_t.h>
# include <linux/delay.h>
# include <linux/seq_file.h>
# include <asm/system.h>
# include <asm/time.h>
# include <asm/machdep.h>
# include <asm/pci-bridge.h>
# include <asm/mpc85xx.h>
# include <asm/prom.h>
# include <asm/mpic.h>
# include <mm/mmu_decl.h>
# include <asm/udbg.h>
# include <sysdev/fsl_soc.h>
2007-07-10 18:47:06 +08:00
# include <sysdev/fsl_pci.h>
2006-01-14 16:57:39 -06:00
# include "mpc85xx.h"
2006-09-21 22:31:26 +04:00
# ifdef CONFIG_CPM2
2006-09-21 22:38:05 +04:00
# include <linux/fs_enet_pd.h>
2006-09-21 22:31:26 +04:00
# include <asm/cpm2.h>
# include <sysdev/cpm2_pic.h>
# include <asm/fs_pd.h>
# endif
2006-02-10 17:01:06 -06:00
# ifdef CONFIG_PCI
2007-06-22 00:23:57 -05:00
static int mpc85xx_exclude_device ( struct pci_controller * hose ,
u_char bus , u_char devfn )
2006-02-10 17:01:06 -06:00
{
if ( bus = = 0 & & PCI_SLOT ( devfn ) = = 0 )
return PCIBIOS_DEVICE_NOT_FOUND ;
else
return PCIBIOS_SUCCESSFUL ;
}
# endif /* CONFIG_PCI */
2006-09-21 22:31:26 +04:00
# ifdef CONFIG_CPM2
2006-10-07 22:08:26 +10:00
static void cpm2_cascade ( unsigned int irq , struct irq_desc * desc )
2006-09-21 22:31:26 +04:00
{
int cascade_irq ;
2006-10-07 22:08:26 +10:00
while ( ( cascade_irq = cpm2_get_irq ( ) ) > = 0 ) {
2006-10-05 20:31:10 -05:00
generic_handle_irq ( cascade_irq ) ;
2006-09-21 22:31:26 +04:00
}
desc - > chip - > eoi ( irq ) ;
}
# endif /* CONFIG_CPM2 */
2006-02-10 17:01:06 -06:00
2007-02-09 09:30:45 -06:00
static void __init mpc85xx_ads_pic_init ( void )
2006-01-14 16:57:39 -06:00
{
2006-08-18 18:03:08 -05:00
struct mpic * mpic ;
struct resource r ;
struct device_node * np = NULL ;
2006-09-21 22:31:26 +04:00
# ifdef CONFIG_CPM2
int irq ;
# endif
2006-08-18 18:03:08 -05:00
np = of_find_node_by_type ( np , " open-pic " ) ;
if ( np = = NULL ) {
printk ( KERN_ERR " Could not find open-pic node \n " ) ;
return ;
}
if ( of_address_to_resource ( np , 0 , & r ) ) {
printk ( KERN_ERR " Could not map mpic register space \n " ) ;
of_node_put ( np ) ;
return ;
}
mpic = mpic_alloc ( np , r . start ,
MPIC_PRIMARY | MPIC_WANTS_RESET | MPIC_BIG_ENDIAN ,
2007-07-03 02:35:35 -05:00
0 , 256 , " OpenPIC " ) ;
2006-08-18 18:03:08 -05:00
BUG_ON ( mpic = = NULL ) ;
of_node_put ( np ) ;
mpic_init ( mpic ) ;
2006-09-21 22:31:26 +04:00
# ifdef CONFIG_CPM2
/* Setup CPM2 PIC */
np = of_find_node_by_type ( NULL , " cpm-pic " ) ;
if ( np = = NULL ) {
printk ( KERN_ERR " PIC init: can not find cpm-pic node \n " ) ;
return ;
}
irq = irq_of_parse_and_map ( np , 0 ) ;
cpm2_pic_init ( np ) ;
set_irq_chained_handler ( irq , cpm2_cascade ) ;
# endif
2006-01-14 16:57:39 -06:00
}
/*
* Setup the architecture
*/
2006-09-21 22:31:26 +04:00
# ifdef CONFIG_CPM2
2006-09-21 22:38:05 +04:00
void init_fcc_ioports ( struct fs_platform_info * fpi )
2006-09-21 22:31:26 +04:00
{
2006-09-21 22:38:05 +04:00
struct io_port * io = cpm2_map ( im_ioport ) ;
int fcc_no = fs_get_fcc_index ( fpi - > fs_no ) ;
int target ;
2006-09-21 22:31:26 +04:00
u32 tempval ;
2006-09-21 22:38:05 +04:00
switch ( fcc_no ) {
case 1 :
tempval = in_be32 ( & io - > iop_pdirb ) ;
tempval & = ~ PB2_DIRB0 ;
tempval | = PB2_DIRB1 ;
out_be32 ( & io - > iop_pdirb , tempval ) ;
tempval = in_be32 ( & io - > iop_psorb ) ;
tempval & = ~ PB2_PSORB0 ;
tempval | = PB2_PSORB1 ;
out_be32 ( & io - > iop_psorb , tempval ) ;
tempval = in_be32 ( & io - > iop_pparb ) ;
tempval | = ( PB2_DIRB0 | PB2_DIRB1 ) ;
out_be32 ( & io - > iop_pparb , tempval ) ;
target = CPM_CLK_FCC2 ;
break ;
case 2 :
tempval = in_be32 ( & io - > iop_pdirb ) ;
tempval & = ~ PB3_DIRB0 ;
tempval | = PB3_DIRB1 ;
out_be32 ( & io - > iop_pdirb , tempval ) ;
tempval = in_be32 ( & io - > iop_psorb ) ;
tempval & = ~ PB3_PSORB0 ;
tempval | = PB3_PSORB1 ;
out_be32 ( & io - > iop_psorb , tempval ) ;
tempval = in_be32 ( & io - > iop_pparb ) ;
tempval | = ( PB3_DIRB0 | PB3_DIRB1 ) ;
out_be32 ( & io - > iop_pparb , tempval ) ;
tempval = in_be32 ( & io - > iop_pdirc ) ;
tempval | = PC3_DIRC1 ;
out_be32 ( & io - > iop_pdirc , tempval ) ;
tempval = in_be32 ( & io - > iop_pparc ) ;
tempval | = PC3_DIRC1 ;
out_be32 ( & io - > iop_pparc , tempval ) ;
target = CPM_CLK_FCC3 ;
break ;
default :
printk ( KERN_ERR " init_fcc_ioports: invalid FCC number \n " ) ;
return ;
}
2006-09-21 22:31:26 +04:00
/* Port C has clocks...... */
tempval = in_be32 ( & io - > iop_psorc ) ;
2006-09-21 22:38:05 +04:00
tempval & = ~ ( PC_CLK ( fpi - > clk_rx - 8 ) | PC_CLK ( fpi - > clk_tx - 8 ) ) ;
2006-09-21 22:31:26 +04:00
out_be32 ( & io - > iop_psorc , tempval ) ;
tempval = in_be32 ( & io - > iop_pdirc ) ;
2006-09-21 22:38:05 +04:00
tempval & = ~ ( PC_CLK ( fpi - > clk_rx - 8 ) | PC_CLK ( fpi - > clk_tx - 8 ) ) ;
2006-09-21 22:31:26 +04:00
out_be32 ( & io - > iop_pdirc , tempval ) ;
tempval = in_be32 ( & io - > iop_pparc ) ;
2006-09-21 22:38:05 +04:00
tempval | = ( PC_CLK ( fpi - > clk_rx - 8 ) | PC_CLK ( fpi - > clk_tx - 8 ) ) ;
2006-09-21 22:31:26 +04:00
out_be32 ( & io - > iop_pparc , tempval ) ;
2006-09-21 22:38:05 +04:00
cpm2_unmap ( io ) ;
2006-09-21 22:31:26 +04:00
/* Configure Serial Interface clock routing.
2006-09-21 22:38:05 +04:00
* First , clear FCC bits to zero ,
2006-09-21 22:31:26 +04:00
* then set the ones we want .
*/
2006-09-21 22:38:05 +04:00
cpm2_clk_setup ( target , fpi - > clk_rx , CPM_CLK_RX ) ;
cpm2_clk_setup ( target , fpi - > clk_tx , CPM_CLK_TX ) ;
2006-09-21 22:31:26 +04:00
}
# endif
2006-02-07 21:29:42 -06:00
static void __init mpc85xx_ads_setup_arch ( void )
2006-01-14 16:57:39 -06:00
{
2006-08-18 18:03:08 -05:00
# ifdef CONFIG_PCI
2006-02-10 17:01:06 -06:00
struct device_node * np ;
2006-08-18 18:03:08 -05:00
# endif
2006-01-14 16:57:39 -06:00
if ( ppc_md . progress )
ppc_md . progress ( " mpc85xx_ads_setup_arch() " , 0 ) ;
2006-09-21 22:31:26 +04:00
# ifdef CONFIG_CPM2
cpm2_reset ( ) ;
# endif
2006-02-10 17:01:06 -06:00
# ifdef CONFIG_PCI
for ( np = NULL ; ( np = of_find_node_by_type ( np , " pci " ) ) ! = NULL ; )
2007-07-10 18:47:06 +08:00
fsl_add_bridge ( np , 1 ) ;
2006-02-10 17:01:06 -06:00
ppc_md . pci_exclude_device = mpc85xx_exclude_device ;
# endif
2006-01-14 16:57:39 -06:00
}
2007-02-09 09:30:45 -06:00
static void mpc85xx_ads_show_cpuinfo ( struct seq_file * m )
2006-01-14 16:57:39 -06:00
{
uint pvid , svid , phid1 ;
uint memsize = total_memory ;
pvid = mfspr ( SPRN_PVR ) ;
svid = mfspr ( SPRN_SVR ) ;
seq_printf ( m , " Vendor \t \t : Freescale Semiconductor \n " ) ;
seq_printf ( m , " Machine \t \t : mpc85xx \n " ) ;
seq_printf ( m , " PVR \t \t : 0x%x \n " , pvid ) ;
seq_printf ( m , " SVR \t \t : 0x%x \n " , svid ) ;
/* Display cpu Pll setting */
phid1 = mfspr ( SPRN_HID1 ) ;
seq_printf ( m , " PLL setting \t : 0x%x \n " , ( ( phid1 > > 24 ) & 0x3f ) ) ;
/* Display the amount of memory */
seq_printf ( m , " Memory \t \t : %d MB \n " , memsize / ( 1024 * 1024 ) ) ;
}
2006-03-30 23:39:57 -06:00
/*
* Called very early , device - tree isn ' t unflattened
*/
static int __init mpc85xx_ads_probe ( void )
2006-01-14 16:57:39 -06:00
{
2007-02-17 16:19:34 -06:00
unsigned long root = of_get_flat_dt_root ( ) ;
return of_flat_dt_is_compatible ( root , " MPC85xxADS " ) ;
2006-01-14 16:57:39 -06:00
}
2006-03-30 23:39:57 -06:00
define_machine ( mpc85xx_ads ) {
. name = " MPC85xx ADS " ,
. probe = mpc85xx_ads_probe ,
. setup_arch = mpc85xx_ads_setup_arch ,
. init_IRQ = mpc85xx_ads_pic_init ,
. show_cpuinfo = mpc85xx_ads_show_cpuinfo ,
. get_irq = mpic_get_irq ,
. restart = mpc85xx_restart ,
. calibrate_decr = generic_calibrate_decr ,
. progress = udbg_progress ,
} ;