2005-04-16 15:20:36 -07:00
/*
* PCI code for DDB5477 .
*
* Copyright ( C ) 2001 MontaVista Software Inc .
* Author : Jun Sun , jsun @ mvista . com or jsun @ junsun . net
*
* Copyright ( C ) 2004 by Ralf Baechle ( ralf @ linux - mips . org )
*
* 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/kernel.h>
# include <linux/init.h>
# include <linux/types.h>
# include <linux/pci.h>
# include <asm/bootinfo.h>
# include <asm/debug.h>
# include <asm/ddb5xxx/ddb5xxx.h>
static struct resource extpci_io_resource = {
2006-06-04 15:14:05 -07:00
. start = DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + 0x4000 ,
. end = DDB_PCI0_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI0_IO_SIZE - 1 ,
. name = " ext pci IO space " ,
. flags = IORESOURCE_IO
2005-04-16 15:20:36 -07:00
} ;
static struct resource extpci_mem_resource = {
2006-06-04 15:14:05 -07:00
. start = DDB_PCI0_MEM_BASE + 0x100000 ,
. end = DDB_PCI0_MEM_BASE + DDB_PCI0_MEM_SIZE - 1 ,
. name = " ext pci memory space " ,
. flags = IORESOURCE_MEM
2005-04-16 15:20:36 -07:00
} ;
static struct resource iopci_io_resource = {
2006-06-04 15:14:05 -07:00
. start = DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE ,
. end = DDB_PCI1_IO_BASE - DDB_PCI_IO_BASE + DDB_PCI1_IO_SIZE - 1 ,
. name = " io pci IO space " ,
. flags = IORESOURCE_IO
2005-04-16 15:20:36 -07:00
} ;
static struct resource iopci_mem_resource = {
2006-06-04 15:14:05 -07:00
. start = DDB_PCI1_MEM_BASE ,
. end = DDB_PCI1_MEM_BASE + DDB_PCI1_MEM_SIZE - 1 ,
. name = " ext pci memory space " ,
. flags = IORESOURCE_MEM
2005-04-16 15:20:36 -07:00
} ;
extern struct pci_ops ddb5477_ext_pci_ops ;
extern struct pci_ops ddb5477_io_pci_ops ;
struct pci_controller ddb5477_ext_controller = {
. pci_ops = & ddb5477_ext_pci_ops ,
. io_resource = & extpci_io_resource ,
. mem_resource = & extpci_mem_resource
} ;
struct pci_controller ddb5477_io_controller = {
. pci_ops = & ddb5477_io_pci_ops ,
. io_resource = & iopci_io_resource ,
. mem_resource = & iopci_mem_resource
} ;
/*
* we fix up irqs based on the slot number .
* The first entry is at AD : 11.
* Fortunately this works because , although we have two pci buses ,
* they all have different slot numbers ( except for rockhopper slot 20
* which is handled below ) .
*
*/
/*
2005-09-03 15:56:17 -07:00
* irq mapping : device - > pci int # - > vrc4377 irq # ,
2005-04-16 15:20:36 -07:00
* ddb5477 board manual page 4 and vrc5477 manual page 46
*/
/*
* based on ddb5477 manual page 11
*/
# define MAX_SLOT_NUM 21
static unsigned char irq_map [ MAX_SLOT_NUM ] = {
/* SLOT: 0, AD:11 */ 0xff ,
/* SLOT: 1, AD:12 */ 0xff ,
/* SLOT: 2, AD:13 */ 0xff ,
/* SLOT: 3, AD:14 */ 0xff ,
/* SLOT: 4, AD:15 */ VRC5477_IRQ_INTA , /* onboard tulip */
/* SLOT: 5, AD:16 */ VRC5477_IRQ_INTB , /* slot 1 */
/* SLOT: 6, AD:17 */ VRC5477_IRQ_INTC , /* slot 2 */
/* SLOT: 7, AD:18 */ VRC5477_IRQ_INTD , /* slot 3 */
/* SLOT: 8, AD:19 */ VRC5477_IRQ_INTE , /* slot 4 */
/* SLOT: 9, AD:20 */ 0xff ,
/* SLOT: 10, AD:21 */ 0xff ,
/* SLOT: 11, AD:22 */ 0xff ,
/* SLOT: 12, AD:23 */ 0xff ,
/* SLOT: 13, AD:24 */ 0xff ,
/* SLOT: 14, AD:25 */ 0xff ,
/* SLOT: 15, AD:26 */ 0xff ,
/* SLOT: 16, AD:27 */ 0xff ,
/* SLOT: 17, AD:28 */ 0xff ,
/* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC , /* vrc5477 ac97 */
/* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB , /* vrc5477 usb peri */
/* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA , /* vrc5477 usb host */
} ;
static unsigned char rockhopperII_irq_map [ MAX_SLOT_NUM ] = {
/* SLOT: 0, AD:11 */ 0xff ,
/* SLOT: 1, AD:12 */ VRC5477_IRQ_INTB , /* onboard AMD PCNET */
/* SLOT: 2, AD:13 */ 0xff ,
/* SLOT: 3, AD:14 */ 0xff ,
/* SLOT: 4, AD:15 */ 14 , /* M5229 ide ISA irq */
/* SLOT: 5, AD:16 */ VRC5477_IRQ_INTD , /* slot 3 */
/* SLOT: 6, AD:17 */ VRC5477_IRQ_INTA , /* slot 4 */
/* SLOT: 7, AD:18 */ VRC5477_IRQ_INTD , /* slot 5 */
/* SLOT: 8, AD:19 */ 0 , /* M5457 modem nop */
/* SLOT: 9, AD:20 */ VRC5477_IRQ_INTA , /* slot 2 */
/* SLOT: 10, AD:21 */ 0xff ,
/* SLOT: 11, AD:22 */ 0xff ,
/* SLOT: 12, AD:23 */ 0xff ,
/* SLOT: 13, AD:24 */ 0xff ,
/* SLOT: 14, AD:25 */ 0xff ,
/* SLOT: 15, AD:26 */ 0xff ,
/* SLOT: 16, AD:27 */ 0xff ,
/* SLOT: 17, AD:28 */ 0 , /* M7101 PMU nop */
/* SLOT: 18, AD:29 */ VRC5477_IRQ_IOPCI_INTC , /* vrc5477 ac97 */
/* SLOT: 19, AD:30 */ VRC5477_IRQ_IOPCI_INTB , /* vrc5477 usb peri */
/* SLOT: 20, AD:31 */ VRC5477_IRQ_IOPCI_INTA , /* vrc5477 usb host */
} ;
int __init pcibios_map_irq ( struct pci_dev * dev , u8 slot , u8 pin )
{
int slot_num ;
unsigned char * slot_irq_map ;
unsigned char irq ;
2005-09-03 15:56:17 -07:00
/*
2005-04-16 15:20:36 -07:00
* We ignore the swizzled slot and pin values . The original
2005-09-03 15:56:17 -07:00
* pci_fixup_irq ( ) codes largely base irq number on the dev slot
2005-04-16 15:20:36 -07:00
* numbers because except for one case they are unique even
* though there are multiple pci buses .
*/
if ( mips_machtype = = MACH_NEC_ROCKHOPPERII )
slot_irq_map = rockhopperII_irq_map ;
else
slot_irq_map = irq_map ;
slot_num = PCI_SLOT ( dev - > devfn ) ;
irq = slot_irq_map [ slot_num ] ;
db_assert ( slot_num < MAX_SLOT_NUM ) ;
db_assert ( irq ! = 0xff ) ;
pci_write_config_byte ( dev , PCI_INTERRUPT_LINE , irq ) ;
if ( mips_machtype = = MACH_NEC_ROCKHOPPERII ) {
/* hack to distinquish overlapping slot 20s, one
2005-09-03 15:56:17 -07:00
* on bus 0 ( ALI USB on the M1535 on the backplane ) ,
2005-04-16 15:20:36 -07:00
* and one on bus 2 ( NEC USB controller on the CPU board )
* Make the M1535 USB - ISA IRQ number 9.
*/
if ( slot_num = = 20 & & dev - > bus - > number = = 0 ) {
pci_write_config_byte ( dev ,
PCI_INTERRUPT_LINE ,
9 ) ;
irq = 9 ;
}
}
return irq ;
}
/* Do platform specific device initialization at pci_enable_device() time */
int pcibios_plat_dev_init ( struct pci_dev * dev )
{
return 0 ;
}
void ddb_pci_reset_bus ( void )
{
u32 temp ;
/*
* I am not sure about the " official " procedure , the following
* steps work as far as I know :
* We first set PCI cold reset bit ( bit 31 ) in PCICTRL - H .
* Then we clear the PCI warm reset bit ( bit 30 ) to 0 in PCICTRL - H .
* The same is true for both PCI channels .
*/
temp = ddb_in32 ( DDB_PCICTL0_H ) ;
temp | = 0x80000000 ;
ddb_out32 ( DDB_PCICTL0_H , temp ) ;
temp & = ~ 0xc0000000 ;
ddb_out32 ( DDB_PCICTL0_H , temp ) ;
temp = ddb_in32 ( DDB_PCICTL1_H ) ;
temp | = 0x80000000 ;
ddb_out32 ( DDB_PCICTL1_H , temp ) ;
temp & = ~ 0xc0000000 ;
ddb_out32 ( DDB_PCICTL1_H , temp ) ;
}