2006-09-27 10:59:17 +04:00
/*
* Low - Level PCI Support for the SH7780
*
* Dustin McIntire ( dustin @ sensoria . com )
* Derived from arch / i386 / kernel / pci - * . c which bore the message :
* ( c ) 1999 - - 2000 Martin Mares < mj @ ucw . cz >
*
* Ported to the new API by Paul Mundt < lethal @ linux - sh . org >
* With cleanup by Paul van Gool < pvangool @ mimotech . com >
*
* May be copied or modified under the terms of the GNU General Public
* License . See linux / COPYING for more information .
*
*/
# undef DEBUG
# 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
2006-11-20 07:55:34 +03:00
# define INTC_BASE 0xffd00000
# define INTC_ICR0 (INTC_BASE+0x0)
# define INTC_ICR1 (INTC_BASE+0x1c)
# define INTC_INTPRI (INTC_BASE+0x10)
# define INTC_INTREQ (INTC_BASE+0x24)
# define INTC_INTMSK0 (INTC_BASE+0x44)
# define INTC_INTMSK1 (INTC_BASE+0x48)
# define INTC_INTMSK2 (INTC_BASE+0x40080)
# define INTC_INTMSKCLR0 (INTC_BASE+0x64)
# define INTC_INTMSKCLR1 (INTC_BASE+0x68)
# define INTC_INTMSKCLR2 (INTC_BASE+0x40084)
# define INTC_INT2MSKR (INTC_BASE+0x40038)
# define INTC_INT2MSKCR (INTC_BASE+0x4003c)
2006-09-27 10:59:17 +04:00
/*
2006-09-27 11:43:28 +04:00
* Initialization . Try all known PCI access methods . Note that we support
* using both PCI BIOS and direct access : in such cases , we use I / O ports
* to access config space .
*
* Note that the platform specific initialization ( BSC registers , and memory
* space mapping ) will be called via the platform defined function
* pcibios_init_platform ( ) .
2006-09-27 10:59:17 +04:00
*/
2006-09-27 11:43:28 +04:00
static int __init sh7780_pci_init ( void )
2006-09-27 10:59:17 +04:00
{
2006-09-27 11:43:28 +04:00
unsigned int id ;
2007-03-12 08:38:59 +03:00
int ret , match = 0 ;
2006-09-27 10:59:17 +04:00
2006-09-27 11:43:28 +04:00
pr_debug ( " PCI: Starting intialization. \n " ) ;
2006-09-27 10:59:17 +04:00
outl ( 0x00000001 , SH7780_PCI_VCR2 ) ; /* Enable PCIC */
/* check for SH7780/SH7780R hardware */
2006-09-27 11:43:28 +04:00
id = pci_read_reg ( SH7780_PCIVID ) ;
2007-03-12 08:38:59 +03:00
if ( ( id & 0xffff ) = = SH7780_VENDOR_ID ) {
switch ( ( id > > 16 ) & 0xffff ) {
case SH7780_DEVICE_ID :
case SH7781_DEVICE_ID :
case SH7785_DEVICE_ID :
match = 1 ;
break ;
}
}
if ( unlikely ( ! match ) ) {
2006-09-27 10:59:17 +04:00
printk ( KERN_ERR " PCI: This is not an SH7780 (%x) \n " , id ) ;
return - ENODEV ;
}
/* Setup the INTC */
ctrl_outl ( 0x00200000 , INTC_ICR0 ) ; /* INTC SH-4 Mode */
ctrl_outl ( 0x00078000 , INTC_INT2MSKCR ) ; /* enable PCIINTA - PCIINTD */
ctrl_outl ( 0x40000000 , INTC_INTMSK1 ) ; /* disable IRL4-7 Interrupt */
ctrl_outl ( 0x0000fffe , INTC_INTMSK2 ) ; /* disable IRL4-7 Interrupt */
ctrl_outl ( 0x80000000 , INTC_INTMSKCLR1 ) ; /* enable IRL0-3 Interrupt */
ctrl_outl ( 0xfffe0000 , INTC_INTMSKCLR2 ) ; /* enable IRL0-3 Interrupt */
2006-09-27 11:43:28 +04:00
if ( ( ret = sh4_pci_check_direct ( ) ) ! = 0 )
2006-09-27 10:59:17 +04:00
return ret ;
return pcibios_init_platform ( ) ;
}
core_initcall ( sh7780_pci_init ) ;
2006-09-27 11:43:28 +04:00
int __init sh7780_pcic_init ( struct sh4_pci_address_map * map )
2006-09-27 10:59:17 +04:00
{
u32 word ;
/*
* This code is unused for some boards as it is done in the
* bootloader and doing it here means the MAC addresses loaded
* by the bootloader get lost .
*/
2006-09-27 11:43:28 +04:00
if ( ! ( map - > flags & SH4_PCIC_NO_RESET ) ) {
2006-09-27 10:59:17 +04:00
/* toggle PCI reset pin */
2006-09-27 11:43:28 +04:00
word = SH4_PCICR_PREFIX | SH4_PCICR_PRST ;
pci_write_reg ( word , SH4_PCICR ) ;
2006-09-27 10:59:17 +04:00
/* Wait for a long time... not 1 sec. but long enough */
mdelay ( 100 ) ;
2006-09-27 11:43:28 +04:00
word = SH4_PCICR_PREFIX ;
pci_write_reg ( word , SH4_PCICR ) ;
2006-09-27 10:59:17 +04:00
}
/* set the command/status bits to:
* Wait Cycle Control + Parity Enable + Bus Master +
* Mem space enable
*/
2006-09-27 11:43:28 +04:00
pci_write_reg ( 0x00000046 , SH7780_PCICMD ) ;
2006-09-27 10:59:17 +04:00
/* define this host as the host bridge */
2006-09-27 11:43:28 +04:00
word = PCI_BASE_CLASS_BRIDGE < < 24 ;
pci_write_reg ( word , SH7780_PCIRID ) ;
2006-09-27 10:59:17 +04:00
/* Set IO and Mem windows to local address
* Make PCI and local address the same for easy 1 to 1 mapping
* Window0 = map - > window0 . size @ non - cached area base = SDRAM
* Window1 = map - > window1 . size @ cached area base = SDRAM
*/
word = ( ( map - > window0 . size - 1 ) & 0x1ff00001 ) | 0x01 ;
2006-09-27 11:43:28 +04:00
pci_write_reg ( 0x07f00001 , SH4_PCILSR0 ) ;
2006-09-27 10:59:17 +04:00
word = ( ( map - > window1 . size - 1 ) & 0x1ff00001 ) | 0x01 ;
2006-09-27 11:43:28 +04:00
pci_write_reg ( 0x00000001 , SH4_PCILSR1 ) ;
2006-09-27 10:59:17 +04:00
/* Set the values on window 0 PCI config registers */
word = P2SEGADDR ( map - > window0 . base ) ;
2006-09-27 11:43:28 +04:00
pci_write_reg ( 0xa8000000 , SH4_PCILAR0 ) ;
pci_write_reg ( 0x08000000 , SH7780_PCIMBAR0 ) ;
2006-09-27 10:59:17 +04:00
/* Set the values on window 1 PCI config registers */
word = P2SEGADDR ( map - > window1 . base ) ;
2006-09-27 11:43:28 +04:00
pci_write_reg ( 0x00000000 , SH4_PCILAR1 ) ;
pci_write_reg ( 0x00000000 , SH7780_PCIMBAR1 ) ;
2006-09-27 10:59:17 +04:00
/* Map IO space into PCI IO window
* The IO window is 64 K - PCIBIOS_MIN_IO in size
* IO addresses will be translated to the
* PCI IO window base address
*/
2006-09-27 11:43:28 +04:00
pr_debug ( " PCI: Mapping IO address 0x%x - 0x%x to base 0x%x \n " ,
PCIBIOS_MIN_IO , ( 64 < < 10 ) ,
SH7780_PCI_IO_BASE + PCIBIOS_MIN_IO ) ;
2006-09-27 10:59:17 +04:00
/* NOTE: I'm ignoring the PCI error IRQs for now..
* TODO : add support for the internal error interrupts and
* DMA interrupts . . .
*/
2007-03-12 08:38:59 +03:00
# ifdef CONFIG_SH_HIGHLANDER
2006-09-27 10:59:17 +04:00
pci_fixup_pcic ( ) ;
# endif
/* 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 ;
pci_write_reg ( word , SH4_PCICR ) ;
2006-09-27 10:59:17 +04:00
return 1 ;
}