2007-03-20 19:19:10 +03:00
/*
2007-08-17 18:26:40 +04:00
* MPC85xx DS Board Setup
2007-03-20 19:19:10 +03:00
*
* Author Xianghua Xiao ( x . xiao @ freescale . com )
2007-07-13 14:05:08 +04:00
* Roy Zang < tie - fei . zang @ freescale . com >
* - Add PCI / PCI Exprees support
2007-03-20 19:19:10 +03:00
* Copyright 2007 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>
2007-07-13 14:05:08 +04:00
# include <linux/pci.h>
2007-03-20 19:19:10 +03:00
# include <linux/kdev_t.h>
# include <linux/delay.h>
# include <linux/seq_file.h>
2007-07-13 14:05:08 +04:00
# include <linux/interrupt.h>
2008-03-15 02:01:30 +03:00
# include <linux/of_platform.h>
2010-07-12 08:36:09 +04:00
# include <linux/memblock.h>
2007-03-20 19:19:10 +03:00
# include <asm/system.h>
# include <asm/time.h>
# include <asm/machdep.h>
2007-07-13 14:05:08 +04:00
# include <asm/pci-bridge.h>
2007-03-20 19:19:10 +03:00
# include <mm/mmu_decl.h>
# include <asm/prom.h>
# include <asm/udbg.h>
# include <asm/mpic.h>
# include <asm/i8259.h>
2009-05-15 09:37:35 +04:00
# include <asm/swiotlb.h>
2007-03-20 19:19:10 +03:00
# include <sysdev/fsl_soc.h>
2007-07-13 14:05:08 +04:00
# include <sysdev/fsl_pci.h>
2011-12-02 10:27:58 +04:00
# include "smp.h"
2007-03-20 19:19:10 +03:00
2011-11-17 21:56:16 +04:00
# include "mpc85xx.h"
2007-03-20 19:19:10 +03:00
# undef DEBUG
# ifdef DEBUG
2008-03-29 00:21:07 +03:00
# define DBG(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args)
2007-03-20 19:19:10 +03:00
# else
# define DBG(fmt, args...)
# endif
2007-07-13 14:05:08 +04:00
# ifdef CONFIG_PPC_I8259
2007-08-17 18:26:40 +04:00
static void mpc85xx_8259_cascade ( unsigned int irq , struct irq_desc * desc )
2007-07-13 14:05:08 +04:00
{
2011-03-25 18:45:20 +03:00
struct irq_chip * chip = irq_desc_get_chip ( desc ) ;
2007-07-13 14:05:08 +04:00
unsigned int cascade_irq = i8259_irq ( ) ;
if ( cascade_irq ! = NO_IRQ ) {
generic_handle_irq ( cascade_irq ) ;
}
2011-03-07 16:59:19 +03:00
chip - > irq_eoi ( & desc - > irq_data ) ;
2007-07-13 14:05:08 +04:00
}
# endif /* CONFIG_PPC_I8259 */
2007-03-20 19:19:10 +03:00
2007-08-17 18:26:40 +04:00
void __init mpc85xx_ds_pic_init ( void )
2007-03-20 19:19:10 +03:00
{
struct mpic * mpic ;
# ifdef CONFIG_PPC_I8259
2011-12-02 10:28:02 +04:00
struct device_node * np ;
2007-03-20 19:19:10 +03:00
struct device_node * cascade_node = NULL ;
int cascade_irq ;
# endif
2008-11-13 16:46:12 +03:00
unsigned long root = of_get_flat_dt_root ( ) ;
2007-03-20 19:19:10 +03:00
2008-11-13 16:46:12 +03:00
if ( of_flat_dt_is_compatible ( root , " fsl,MPC8572DS-CAMP " ) ) {
2011-12-02 10:28:02 +04:00
mpic = mpic_alloc ( NULL , 0 ,
2011-07-12 11:49:43 +04:00
MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
MPIC_SINGLE_DEST_CPU ,
2008-11-13 16:46:12 +03:00
0 , 256 , " OpenPIC " ) ;
} else {
2011-12-02 10:28:02 +04:00
mpic = mpic_alloc ( NULL , 0 ,
2011-12-02 10:28:03 +04:00
MPIC_WANTS_RESET |
2008-10-28 21:01:39 +03:00
MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
MPIC_SINGLE_DEST_CPU ,
2007-07-03 11:35:35 +04:00
0 , 256 , " OpenPIC " ) ;
2008-11-13 16:46:12 +03:00
}
2007-03-20 19:19:10 +03:00
BUG_ON ( mpic = = NULL ) ;
mpic_init ( mpic ) ;
# ifdef CONFIG_PPC_I8259
/* Initialize the i8259 controller */
for_each_node_by_type ( np , " interrupt-controller " )
2007-05-03 11:26:52 +04:00
if ( of_device_is_compatible ( np , " chrp,iic " ) ) {
2007-03-20 19:19:10 +03:00
cascade_node = np ;
break ;
}
if ( cascade_node = = NULL ) {
printk ( KERN_DEBUG " Could not find i8259 PIC \n " ) ;
return ;
}
cascade_irq = irq_of_parse_and_map ( cascade_node , 0 ) ;
if ( cascade_irq = = NO_IRQ ) {
printk ( KERN_ERR " Failed to map cascade interrupt \n " ) ;
return ;
}
2007-08-17 18:26:40 +04:00
DBG ( " mpc85xxds: cascade mapped to irq %d \n " , cascade_irq ) ;
2007-03-20 19:19:10 +03:00
i8259_init ( cascade_node , 0 ) ;
of_node_put ( cascade_node ) ;
2011-03-25 18:45:20 +03:00
irq_set_chained_handler ( cascade_irq , mpc85xx_8259_cascade ) ;
2007-03-20 19:19:10 +03:00
# endif /* CONFIG_PPC_I8259 */
}
2007-07-13 14:05:08 +04:00
# ifdef CONFIG_PCI
2007-08-17 18:26:40 +04:00
static int primary_phb_addr ;
2007-08-17 08:55:55 +04:00
extern int uli_exclude_device ( struct pci_controller * hose ,
u_char bus , u_char devfn ) ;
2007-07-13 14:05:08 +04:00
2007-08-17 08:55:55 +04:00
static int mpc85xx_exclude_device ( struct pci_controller * hose ,
u_char bus , u_char devfn )
2007-07-13 14:05:08 +04:00
{
2007-08-17 18:26:40 +04:00
struct device_node * node ;
2007-08-17 08:55:55 +04:00
struct resource rsrc ;
2007-07-13 14:05:08 +04:00
2007-12-10 06:33:21 +03:00
node = hose - > dn ;
2007-08-17 08:55:55 +04:00
of_address_to_resource ( node , 0 , & rsrc ) ;
2007-07-13 14:05:08 +04:00
2007-08-17 18:26:40 +04:00
if ( ( rsrc . start & 0xfffff ) = = primary_phb_addr ) {
2007-08-17 08:55:55 +04:00
return uli_exclude_device ( hose , bus , devfn ) ;
}
2007-07-13 14:05:08 +04:00
2007-08-17 08:55:55 +04:00
return PCIBIOS_SUCCESSFUL ;
2007-07-13 14:05:08 +04:00
}
# endif /* CONFIG_PCI */
2007-03-20 19:19:10 +03:00
/*
* Setup the architecture
*/
2007-08-17 18:26:40 +04:00
static void __init mpc85xx_ds_setup_arch ( void )
2007-03-20 19:19:10 +03:00
{
2007-07-13 14:05:08 +04:00
# ifdef CONFIG_PCI
struct device_node * np ;
2009-05-15 09:37:35 +04:00
struct pci_controller * hose ;
2007-07-13 14:05:08 +04:00
# endif
2009-05-15 09:37:35 +04:00
dma_addr_t max = 0xffffffff ;
2007-07-13 14:05:08 +04:00
2007-03-20 19:19:10 +03:00
if ( ppc_md . progress )
2007-08-17 18:26:40 +04:00
ppc_md . progress ( " mpc85xx_ds_setup_arch() " , 0 ) ;
2007-03-20 19:19:10 +03:00
2007-07-13 14:05:08 +04:00
# ifdef CONFIG_PCI
2007-10-04 09:28:43 +04:00
for_each_node_by_type ( np , " pci " ) {
if ( of_device_is_compatible ( np , " fsl,mpc8540-pci " ) | |
2009-04-15 23:38:40 +04:00
of_device_is_compatible ( np , " fsl,mpc8548-pcie " ) | |
of_device_is_compatible ( np , " fsl,p2020-pcie " ) ) {
2007-10-04 09:28:43 +04:00
struct resource rsrc ;
of_address_to_resource ( np , 0 , & rsrc ) ;
if ( ( rsrc . start & 0xfffff ) = = primary_phb_addr )
fsl_add_bridge ( np , 1 ) ;
else
fsl_add_bridge ( np , 0 ) ;
2009-05-15 09:37:35 +04:00
hose = pci_find_hose_for_OF_device ( np ) ;
max = min ( max , hose - > dma_window_base_cur +
hose - > dma_window_size ) ;
2007-10-04 09:28:43 +04:00
}
2007-07-13 14:05:08 +04:00
}
2007-10-04 09:28:43 +04:00
2007-08-17 08:55:55 +04:00
ppc_md . pci_exclude_device = mpc85xx_exclude_device ;
2007-07-13 14:05:08 +04:00
# endif
2008-11-19 18:25:29 +03:00
mpc85xx_smp_init ( ) ;
2009-05-15 09:37:35 +04:00
# ifdef CONFIG_SWIOTLB
2010-07-12 08:36:09 +04:00
if ( memblock_end_of_DRAM ( ) > max ) {
2009-05-15 09:37:35 +04:00
ppc_swiotlb_enable = 1 ;
2009-08-04 23:08:23 +04:00
set_pci_dma_ops ( & swiotlb_dma_ops ) ;
2009-08-04 23:08:22 +04:00
ppc_md . pci_dma_dev_setup = pci_dma_dev_setup_swiotlb ;
2009-05-15 09:37:35 +04:00
}
# endif
2007-08-17 18:26:40 +04:00
printk ( " MPC85xx DS board from Freescale Semiconductor \n " ) ;
2007-03-20 19:19:10 +03:00
}
/*
* Called very early , device - tree isn ' t unflattened
*/
static int __init mpc8544_ds_probe ( void )
{
unsigned long root = of_get_flat_dt_root ( ) ;
2007-08-17 18:26:40 +04:00
if ( of_flat_dt_is_compatible ( root , " MPC8544DS " ) ) {
# ifdef CONFIG_PCI
primary_phb_addr = 0xb000 ;
# endif
return 1 ;
}
2009-04-15 23:38:40 +04:00
return 0 ;
2007-03-20 19:19:10 +03:00
}
2011-11-17 21:56:17 +04:00
machine_device_initcall ( mpc8544_ds , mpc85xx_common_publish_devices ) ;
machine_device_initcall ( mpc8572_ds , mpc85xx_common_publish_devices ) ;
machine_device_initcall ( p2020_ds , mpc85xx_common_publish_devices ) ;
2008-03-15 02:01:30 +03:00
2009-05-15 09:37:35 +04:00
machine_arch_initcall ( mpc8544_ds , swiotlb_setup_bus_notifier ) ;
machine_arch_initcall ( mpc8572_ds , swiotlb_setup_bus_notifier ) ;
machine_arch_initcall ( p2020_ds , swiotlb_setup_bus_notifier ) ;
2007-09-11 10:25:43 +04:00
/*
* Called very early , device - tree isn ' t unflattened
*/
static int __init mpc8572_ds_probe ( void )
{
unsigned long root = of_get_flat_dt_root ( ) ;
if ( of_flat_dt_is_compatible ( root , " fsl,MPC8572DS " ) ) {
# ifdef CONFIG_PCI
primary_phb_addr = 0x8000 ;
# endif
return 1 ;
}
2009-04-15 23:38:40 +04:00
return 0 ;
}
/*
* Called very early , device - tree isn ' t unflattened
*/
static int __init p2020_ds_probe ( void )
{
unsigned long root = of_get_flat_dt_root ( ) ;
if ( of_flat_dt_is_compatible ( root , " fsl,P2020DS " ) ) {
# ifdef CONFIG_PCI
primary_phb_addr = 0x9000 ;
# endif
return 1 ;
}
return 0 ;
2007-09-11 10:25:43 +04:00
}
2007-03-20 19:19:10 +03:00
define_machine ( mpc8544_ds ) {
. name = " MPC8544 DS " ,
. probe = mpc8544_ds_probe ,
2007-08-17 18:26:40 +04:00
. setup_arch = mpc85xx_ds_setup_arch ,
. init_IRQ = mpc85xx_ds_pic_init ,
2007-09-10 23:30:33 +04:00
# ifdef CONFIG_PCI
2007-07-13 14:05:08 +04:00
. pcibios_fixup_bus = fsl_pcibios_fixup_bus ,
2007-09-10 23:30:33 +04:00
# endif
2007-03-20 19:19:10 +03:00
. get_irq = mpic_get_irq ,
2007-10-04 10:04:57 +04:00
. restart = fsl_rstcr_restart ,
2007-03-20 19:19:10 +03:00
. calibrate_decr = generic_calibrate_decr ,
. progress = udbg_progress ,
} ;
2007-09-11 10:25:43 +04:00
define_machine ( mpc8572_ds ) {
. name = " MPC8572 DS " ,
. probe = mpc8572_ds_probe ,
. setup_arch = mpc85xx_ds_setup_arch ,
. init_IRQ = mpc85xx_ds_pic_init ,
# ifdef CONFIG_PCI
. pcibios_fixup_bus = fsl_pcibios_fixup_bus ,
# endif
. get_irq = mpic_get_irq ,
2007-10-04 10:04:57 +04:00
. restart = fsl_rstcr_restart ,
2007-09-11 10:25:43 +04:00
. calibrate_decr = generic_calibrate_decr ,
. progress = udbg_progress ,
} ;
2009-04-15 23:38:40 +04:00
define_machine ( p2020_ds ) {
. name = " P2020 DS " ,
. probe = p2020_ds_probe ,
. setup_arch = mpc85xx_ds_setup_arch ,
. init_IRQ = mpc85xx_ds_pic_init ,
# ifdef CONFIG_PCI
. pcibios_fixup_bus = fsl_pcibios_fixup_bus ,
# endif
. get_irq = mpic_get_irq ,
. restart = fsl_rstcr_restart ,
. calibrate_decr = generic_calibrate_decr ,
. progress = udbg_progress ,
} ;