2006-09-27 10:59:17 +04:00
/*
2009-04-17 15:37:16 +04:00
* Low - Level PCI Support for the SH7780
2006-09-27 10:59:17 +04:00
*
2009-04-17 15:37:16 +04:00
* Copyright ( C ) 2005 - 2009 Paul Mundt
2006-09-27 10:59:17 +04:00
*
2009-04-17 15:37:16 +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 .
2006-09-27 10:59:17 +04:00
*/
# include <linux/types.h>
# include <linux/kernel.h>
# include <linux/init.h>
# include <linux/pci.h>
# include <linux/errno.h>
# include <linux/delay.h>
2006-09-27 11:43:28 +04:00
# include "pci-sh4.h"
2006-09-27 10:59:17 +04:00
2009-04-20 13:29:22 +04:00
static struct resource sh7785_io_resource = {
. name = " SH7785_IO " ,
. start = SH7780_PCI_IO_BASE ,
. end = SH7780_PCI_IO_BASE + SH7780_PCI_IO_SIZE - 1 ,
. flags = IORESOURCE_IO
} ;
static struct resource sh7785_mem_resource = {
. name = " SH7785_mem " ,
. start = SH7780_PCI_MEMORY_BASE ,
. end = SH7780_PCI_MEMORY_BASE + SH7780_PCI_MEM_SIZE - 1 ,
. flags = IORESOURCE_MEM
} ;
static struct pci_channel sh7780_pci_controller = {
. pci_ops = & sh4_pci_ops ,
. mem_resource = & sh7785_mem_resource ,
2009-04-20 13:42:00 +04:00
. mem_offset = 0x00000000 ,
2009-04-20 13:29:22 +04:00
. io_resource = & sh7785_io_resource ,
2009-04-20 13:42:00 +04:00
. io_offset = 0x00000000 ,
2009-05-26 19:12:58 +04:00
. io_map_base = SH7780_PCI_IO_BASE ,
2009-04-20 13:29:22 +04:00
} ;
static struct sh4_pci_address_map sh7780_pci_map = {
. window0 = {
# if defined(CONFIG_32BIT)
. base = SH7780_32BIT_DDR_BASE_ADDR ,
. size = 0x40000000 ,
# else
. base = SH7780_CS0_BASE_ADDR ,
. size = 0x20000000 ,
# endif
} ,
} ;
static int __init sh7780_pci_init ( void )
2006-09-27 10:59:17 +04:00
{
2009-04-20 13:29:22 +04:00
struct pci_channel * chan = & sh7780_pci_controller ;
2006-09-27 11:43:28 +04:00
unsigned int id ;
2009-04-17 10:05:19 +04:00
const char * type = NULL ;
int ret ;
2009-04-20 13:29:22 +04:00
u32 word ;
2006-09-27 10:59:17 +04:00
2009-04-17 10:05:19 +04:00
printk ( KERN_NOTICE " PCI: Starting intialization. \n " ) ;
2006-09-27 10:59:17 +04:00
2008-02-19 15:35:04 +03:00
chan - > reg_base = 0xfe040000 ;
2009-04-17 10:05:19 +04:00
/* Enable CPU access to the PCIC registers. */
__raw_writel ( PCIECR_ENBL , PCIECR ) ;
2006-09-27 10:59:17 +04:00
2009-04-17 10:05:19 +04:00
id = __raw_readw ( chan - > reg_base + SH7780_PCIVID ) ;
if ( id ! = SH7780_VENDOR_ID ) {
printk ( KERN_ERR " PCI: Unknown vendor ID 0x%04x. \n " , id ) ;
return - ENODEV ;
2007-03-12 08:38:59 +03:00
}
2009-04-17 10:05:19 +04:00
id = __raw_readw ( chan - > reg_base + SH7780_PCIDID ) ;
type = ( id = = SH7763_DEVICE_ID ) ? " SH7763 " :
( id = = SH7780_DEVICE_ID ) ? " SH7780 " :
( id = = SH7781_DEVICE_ID ) ? " SH7781 " :
( id = = SH7785_DEVICE_ID ) ? " SH7785 " :
NULL ;
if ( unlikely ( ! type ) ) {
printk ( KERN_ERR " PCI: Found an unsupported Renesas host "
" controller, device id 0x%04x. \n " , id ) ;
return - EINVAL ;
2006-09-27 10:59:17 +04:00
}
2009-04-17 10:05:19 +04:00
printk ( KERN_NOTICE " PCI: Found a Renesas %s host "
" controller, revision %d. \n " , type ,
__raw_readb ( chan - > reg_base + SH7780_PCIRID ) ) ;
2009-03-11 09:46:14 +03:00
if ( ( ret = sh4_pci_check_direct ( chan ) ) ! = 0 )
2006-09-27 10:59:17 +04:00
return ret ;
2009-04-17 11:38:00 +04:00
/*
* Set the class and sub - class codes .
*/
2009-04-17 10:08:01 +04:00
__raw_writeb ( PCI_CLASS_BRIDGE_HOST > > 8 ,
chan - > reg_base + SH7780_PCIBCC ) ;
__raw_writeb ( PCI_CLASS_BRIDGE_HOST & 0xff ,
chan - > reg_base + SH7780_PCISUB ) ;
2009-04-17 09:09:09 +04:00
2009-04-17 15:37:16 +04:00
/*
* Set IO and Mem windows to local address
2006-09-27 10:59:17 +04:00
* Make PCI and local address the same for easy 1 to 1 mapping
*/
2009-04-17 12:21:36 +04:00
pci_write_reg ( chan , sh7780_pci_map . window0 . size - 0xfffff , SH4_PCILSR0 ) ;
2006-09-27 10:59:17 +04:00
/* Set the values on window 0 PCI config registers */
2009-04-17 12:21:36 +04:00
pci_write_reg ( chan , sh7780_pci_map . window0 . base , SH4_PCILAR0 ) ;
pci_write_reg ( chan , sh7780_pci_map . window0 . base , SH7780_PCIMBAR0 ) ;
2006-09-27 10:59:17 +04:00
2009-04-17 15:37:16 +04:00
pci_write_reg ( chan , 0x0000380f , SH4_PCIAINTM ) ;
/* Set up standard PCI config registers */
__raw_writew ( 0xFB00 , chan - > reg_base + SH7780_PCISTATUS ) ;
__raw_writew ( 0x0047 , chan - > reg_base + SH7780_PCICMD ) ;
__raw_writew ( 0x1912 , chan - > reg_base + SH7780_PCISVID ) ;
__raw_writew ( 0x0001 , chan - > reg_base + SH7780_PCISID ) ;
__raw_writeb ( 0x00 , chan - > reg_base + SH7780_PCIPIF ) ;
2007-03-28 19:07:35 +04:00
/* Apply any last-minute PCIC fixups */
2009-03-11 09:41:51 +03:00
pci_fixup_pcic ( chan ) ;
2006-09-27 10:59:17 +04:00
2009-04-17 15:37:16 +04:00
pci_write_reg ( chan , 0xfd000000 , SH7780_PCIMBR0 ) ;
pci_write_reg ( chan , 0x00fc0000 , SH7780_PCIMBMR0 ) ;
# ifdef CONFIG_32BIT
pci_write_reg ( chan , 0xc0000000 , SH7780_PCIMBR2 ) ;
pci_write_reg ( chan , 0x20000000 - SH7780_PCI_IO_SIZE , SH7780_PCIMBMR2 ) ;
# endif
/* Set IOBR for windows containing area specified in pci.h */
pci_write_reg ( chan , chan - > io_resource - > start & ~ ( SH7780_PCI_IO_SIZE - 1 ) ,
SH7780_PCIIOBR ) ;
pci_write_reg ( chan , ( ( SH7780_PCI_IO_SIZE - 1 ) & ( 7 < < 18 ) ) ,
SH7780_PCIIOBMR ) ;
2006-09-27 10:59:17 +04:00
/* SH7780 init done, set central function init complete */
/* use round robin mode to stop a device starving/overruning */
2006-09-27 11:43:28 +04:00
word = SH4_PCICR_PREFIX | SH4_PCICR_CFIN | SH4_PCICR_FTO ;
2009-03-11 09:41:51 +03:00
pci_write_reg ( chan , word , SH4_PCICR ) ;
2006-09-27 10:59:17 +04:00
2009-04-20 13:29:22 +04:00
register_pci_controller ( chan ) ;
2009-03-11 09:46:14 +03:00
return 0 ;
2006-09-27 10:59:17 +04:00
}
2009-04-20 13:29:22 +04:00
arch_initcall ( sh7780_pci_init ) ;