2009-06-15 09:38:18 +02:00
/*
2011-03-11 08:02:44 +01:00
* Copyright 2008 - 2011 DENX Software Engineering GmbH
2009-06-15 09:38:18 +02:00
* Author : Heiko Schocher < hs @ denx . de >
*
* Description :
2012-05-08 15:57:20 +02:00
* Keymile 83 xx platform specific routines .
2009-06-15 09:38:18 +02: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 .
*/
# include <linux/stddef.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/errno.h>
# include <linux/reboot.h>
# include <linux/pci.h>
# include <linux/kdev_t.h>
# include <linux/major.h>
# include <linux/console.h>
# include <linux/delay.h>
# include <linux/seq_file.h>
# include <linux/root_dev.h>
# include <linux/initrd.h>
# include <linux/of_platform.h>
# include <linux/of_device.h>
2011-07-26 16:09:06 -07:00
# include <linux/atomic.h>
2012-12-07 16:09:13 +01:00
# include <linux/time.h>
# include <linux/io.h>
2009-06-15 09:38:18 +02:00
# include <asm/machdep.h>
# include <asm/ipic.h>
# include <asm/irq.h>
# include <asm/prom.h>
# include <asm/udbg.h>
# include <sysdev/fsl_soc.h>
# include <sysdev/fsl_pci.h>
# include <asm/qe.h>
# include <asm/qe_ic.h>
# include "mpc83xx.h"
# define SVR_REV(svr) (((svr) >> 0) & 0xFFFF) /* Revision field */
2012-12-07 16:09:14 +01:00
static void quirk_mpc8360e_qe_enet10 ( void )
{
/*
* handle mpc8360E Erratum QE_ENET10 :
* RGMII AC values do not meet the specification
*/
uint svid = mfspr ( SPRN_SVR ) ;
struct device_node * np_par ;
struct resource res ;
void __iomem * base ;
int ret ;
np_par = of_find_node_by_name ( NULL , " par_io " ) ;
if ( np_par = = NULL ) {
pr_warn ( " %s couldn;t find par_io node \n " , __func__ ) ;
return ;
}
/* Map Parallel I/O ports registers */
ret = of_address_to_resource ( np_par , 0 , & res ) ;
if ( ret ) {
pr_warn ( " %s couldn;t map par_io registers \n " , __func__ ) ;
return ;
}
base = ioremap ( res . start , res . end - res . start + 1 ) ;
/*
* set output delay adjustments to default values according
* table 5 in Errata Rev . 5 , 9 / 2011 :
*
* write 0 b01 to UCC1 bits 18 : 19
* write 0 b01 to UCC2 option 1 bits 4 : 5
* write 0 b01 to UCC2 option 2 bits 16 : 17
*/
clrsetbits_be32 ( ( base + 0xa8 ) , 0x0c00f000 , 0x04005000 ) ;
/*
* set output delay adjustments to default values according
* table 3 - 13 in Reference Manual Rev .3 05 / 2010 :
*
* write 0 b01 to UCC2 option 2 bits 16 : 17
* write 0 b0101 to UCC1 bits 20 : 23
* write 0 b0101 to UCC2 option 1 bits 24 : 27
*/
clrsetbits_be32 ( ( base + 0xac ) , 0x0000cff0 , 0x00004550 ) ;
if ( SVR_REV ( svid ) = = 0x0021 ) {
/*
* UCC2 option 1 : write 0 b1010 to bits 24 : 27
* at address IMMRBAR + 0x14AC
*/
clrsetbits_be32 ( ( base + 0xac ) , 0x000000f0 , 0x000000a0 ) ;
} else if ( SVR_REV ( svid ) = = 0x0020 ) {
/*
* UCC1 : write 0 b11 to bits 18 : 19
* at address IMMRBAR + 0x14A8
*/
setbits32 ( ( base + 0xa8 ) , 0x00003000 ) ;
/*
* UCC2 option 1 : write 0 b11 to bits 4 : 5
* at address IMMRBAR + 0x14A8
*/
setbits32 ( ( base + 0xa8 ) , 0x0c000000 ) ;
/*
* UCC2 option 2 : write 0 b11 to bits 16 : 17
* at address IMMRBAR + 0x14AC
*/
setbits32 ( ( base + 0xac ) , 0x0000c000 ) ;
}
iounmap ( base ) ;
of_node_put ( np_par ) ;
}
2009-06-15 09:38:18 +02:00
/* ************************************************************************
*
* Setup the architecture
*
*/
2011-03-11 08:02:44 +01:00
static void __init mpc83xx_km_setup_arch ( void )
2009-06-15 09:38:18 +02:00
{
2011-11-17 18:48:48 +04:00
# ifdef CONFIG_QUICC_ENGINE
2009-06-15 09:38:18 +02:00
struct device_node * np ;
2011-11-17 18:48:48 +04:00
# endif
2009-06-15 09:38:18 +02:00
if ( ppc_md . progress )
2011-03-11 08:02:44 +01:00
ppc_md . progress ( " kmpbec83xx_setup_arch() " , 0 ) ;
2009-06-15 09:38:18 +02:00
2011-11-17 18:48:48 +04:00
mpc83xx_setup_pci ( ) ;
2009-06-15 09:38:18 +02:00
# ifdef CONFIG_QUICC_ENGINE
qe_reset ( ) ;
np = of_find_node_by_name ( NULL , " par_io " ) ;
if ( np ! = NULL ) {
par_io_init ( np ) ;
of_node_put ( np ) ;
2011-03-11 08:02:44 +01:00
for_each_node_by_name ( np , " spi " )
par_io_of_config ( np ) ;
2012-05-08 15:57:19 +02:00
for_each_node_by_name ( np , " ucc " )
2009-06-15 09:38:18 +02:00
par_io_of_config ( np ) ;
}
np = of_find_compatible_node ( NULL , " network " , " ucc_geth " ) ;
if ( np ! = NULL ) {
2012-12-07 16:09:14 +01:00
quirk_mpc8360e_qe_enet10 ( ) ;
2009-06-15 09:38:18 +02:00
of_node_put ( np ) ;
}
2012-05-08 15:57:20 +02:00
# endif /* CONFIG_QUICC_ENGINE */
2009-06-15 09:38:18 +02:00
}
2011-11-17 18:48:47 +04:00
machine_device_initcall ( mpc83xx_km , mpc83xx_declare_of_platform_devices ) ;
2009-06-15 09:38:18 +02:00
2011-03-11 08:02:44 +01:00
/* list of the supported boards */
static char * board [ ] __initdata = {
" Keymile,KMETER1 " ,
" Keymile,kmpbec8321 " ,
NULL
} ;
2009-06-15 09:38:18 +02:00
/*
* Called very early , MMU is off , device - tree isn ' t unflattened
*/
2011-03-11 08:02:44 +01:00
static int __init mpc83xx_km_probe ( void )
2009-06-15 09:38:18 +02:00
{
2011-03-11 08:02:44 +01:00
unsigned long node = of_get_flat_dt_root ( ) ;
int i = 0 ;
2009-06-15 09:38:18 +02:00
2011-03-11 08:02:44 +01:00
while ( board [ i ] ) {
if ( of_flat_dt_is_compatible ( node , board [ i ] ) )
break ;
i + + ;
}
return ( board [ i ] ! = NULL ) ;
2009-06-15 09:38:18 +02:00
}
2011-03-11 08:02:44 +01:00
define_machine ( mpc83xx_km ) {
. name = " mpc83xx-km-platform " ,
. probe = mpc83xx_km_probe ,
. setup_arch = mpc83xx_km_setup_arch ,
2011-07-22 23:55:42 +04:00
. init_IRQ = mpc83xx_ipic_and_qe_init_IRQ ,
2009-06-15 09:38:18 +02:00
. get_irq = ipic_get_irq ,
. restart = mpc83xx_restart ,
. time_init = mpc83xx_time_init ,
. calibrate_decr = generic_calibrate_decr ,
. progress = udbg_progress ,
} ;