/*
 * (C) Copyright 2001
 * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */



#ifndef _PCI_PIP405_H
#define _PCI_PIP405_H



#define TRUE 1
#define FALSE 0		
#define MAX_PCI_BASE_REG	6 /* max six mem description per PCI dev */
#define DESC_IS_IO				1 /* IO Attribute */
#define DESC_IS_MEM				2 /* Memory attribute     */
#define DESC_IS_PREFETCH	4 /* Memory is Prefetchable */
#define DESC_IS_LOWMEM		8 /* locate below 1M */
#define DESC_IS_64BIT			0x10 /* dual address cycles */
#define DESC_IS_NOT_VALID	0 /* Memory description is nat valid    */

/*----------------------------------------------------------------------------+
| 405GP PCI core memory map defines.
+----------------------------------------------------------------------------*/
#define MIN_PCI_MEMADDR1    0x80000000
#define MIN_PCI_MEMADDR2    0x00000000
#define MIN_PLB_PCI_IOADDR  0xE8000000  /* PLB side of PCI I/O address space */
#define MIN_PCI_PCI_IOADDR1 0x00000000  /* PCI side of PCI I/O address space */
#define MAX_PCI_PCI_IOADDR1 0x00010000  /* PCI side of PCI I/O address space */
#define MIN_PCI_PCI_IOADDR2 0x00800000  /* PCI side of PCI I/O address space */
#define MAX_PCI_DEVICES     32
#define MAX_PCI_FUNCTIONS		7
/*----------------------------------------------------------------------------+
| Defines for the 405GP PCI Config address and data registers followed by
| defines for the standard PCI device configuration header.
+----------------------------------------------------------------------------*/
#define PCICFGADR       0xEEC00000
#define PCICFGDATA      0xEEC00004

#define PCIVENDORID     0x00
#define PCIDEVICEID     0x02
#define PCICMD          0x04
  #define SERR_EN       0x0100
  #define BM_EN         0x0004
  #define MEM_EN        0x0002
  #define IO_EN         0x0001
#define PCISTATUS       0x06
  #define CAPABLE_66MHZ 0x0020
#define PCIREVID        0x08
#define PCICLASSPI      0x09
#define PCICLASSCODE    0x0A
#define PCICACHELINE    0x0C
#define PCILATENCYTIM   0x0D
#define PCIHEADERTYPE   0x0E
#define PCIBIST         0x0F
#define PCIBASEADDR0    0x10
#define PCIBASEADDR1    0x14
#define PCIBASEADDR2    0x18
#define PCISSVENDORID   0x2C
#define PCISSDEVICEID   0x2E
#define PCIINTLINE      0x3C
#define PCIINTPIN       0x3D
#define PCIMINGRANT     0x3E
#define PCIMAXLATENCY   0x3F

#define PCIBUSNUM       0x40        /* 405GP specific parameters */
#define PCISUBBUSNUM    0x41
#define PCIDISCOUNT     0x42
#define PCIBRDGOPT1     0x4A
#define PCIBRDGOPT2     0x60

/*----------------------------------------------------------------------------+
| Defines for 405GP PCI Master local configuration regs.
+----------------------------------------------------------------------------*/
#define PMM0LA          0xEF400000
#define PMM0MA          0xEF400004
#define PMM0PCILA       0xEF400008
#define PMM0PCIHA       0xEF40000C
#define PMM1LA          0xEF400010
#define PMM1MA          0xEF400014
#define PMM1PCILA       0xEF400018
#define PMM1PCIHA       0xEF40001C
#define PMM2LA          0xEF400020
#define PMM2MA          0xEF400024
#define PMM2PCILA       0xEF400028
#define PMM2PCIHA       0xEF40002C

/*----------------------------------------------------------------------------+
| Defines for 405GP PCI Target local configuration regs.
+----------------------------------------------------------------------------*/
#define PTM1MS          0xEF400030
#define PTM1LA          0xEF400034
#define PTM2MS          0xEF400038
#define PTM2LA          0xEF40003C

/*-----------------------------------------------------------------------------+
|       PCI-PCI bridge header
+-----------------------------------------------------------------------------*/
#define PCIPCI_PRIMARYBUS       0x18
#define PCIPCI_SECONDARYBUS     0x19
#define PCIPCI_SUBORDINATEBUS   0x1A
#define PCIPCI_SECONDARYLATENCY 0x1B
#define PCIPCI_IOBASE           0x1C
#define PCIPCI_IOLIMIT          0x1D
#define PCIPCI_SECONDARYSTATUS  0x1E
#define PCIPCI_MEMBASE          0x20
#define PCIPCI_MEMLIMIT         0x22
#define PCIPCI_PREFETCHMEMBASE  0x24
#define PCIPCI_PREFETCHMEMLIMIT 0x26
#define PCIPCI_IOBASEUPPER16    0x30
#define PCIPCI_IOLIMITUPPER16   0x32

#define PCIDEVID_405GP 	0x0

/* Standard device configuration register offsets */
/* Note that only modulo-4 addresses are written to the address register */

#define	PCI_CFG_VENDOR_ID	0x00
#define	PCI_CFG_DEVICE_ID	0x02
#define	PCI_CFG_COMMAND		0x04
#define	PCI_CFG_STATUS		0x06
#define	PCI_CFG_REVISION	0x08
#define	PCI_CFG_PROGRAMMING_IF	0x09
#define	PCI_CFG_SUBCLASS	0x0a
#define	PCI_CFG_CLASS		0x0b
#define	PCI_CFG_CACHE_LINE_SIZE	0x0c
#define	PCI_CFG_LATENCY_TIMER	0x0d
#define	PCI_CFG_HEADER_TYPE	0x0e
#define	PCI_CFG_BIST		0x0f
#define	PCI_CFG_BASE_ADDRESS_0	0x10
#define	PCI_CFG_BASE_ADDRESS_1	0x14
#define	PCI_CFG_BASE_ADDRESS_2	0x18
#define	PCI_CFG_BASE_ADDRESS_3	0x1c
#define	PCI_CFG_BASE_ADDRESS_4	0x20
#define	PCI_CFG_BASE_ADDRESS_5	0x24
#define	PCI_CFG_CIS		0x28
#define	PCI_CFG_SUB_VENDER_ID	0x2c
#define	PCI_CFG_SUB_SYSTEM_ID	0x2e
#define	PCI_CFG_EXPANSION_ROM	0x30
#define	PCI_CFG_RESERVED_0	0x34
#define	PCI_CFG_RESERVED_1	0x38
#define	PCI_CFG_DEV_INT_LINE	0x3c
#define	PCI_CFG_DEV_INT_PIN	0x3d
#define	PCI_CFG_MIN_GRANT	0x3e
#define	PCI_CFG_MAX_LATENCY	0x3f
#define PCI_CFG_SPECIAL_USE     0x41
#define PCI_CFG_MODE            0x43


/* PCI-to-PCI bridge configuration register offsets */
/* Note that only modulo-4 addresses are written to the address register */

#define	PCI_CFG_PRIMARY_BUS	0x18
#define	PCI_CFG_SECONDARY_BUS	0x19
#define	PCI_CFG_SUBORDINATE_BUS	0x1a
#define	PCI_CFG_SEC_LATENCY	0x1b
#define	PCI_CFG_IO_BASE		0x1c
#define	PCI_CFG_IO_LIMIT	0x1d
#define	PCI_CFG_SEC_STATUS	0x1e
#define	PCI_CFG_MEM_BASE	0x20
#define	PCI_CFG_MEM_LIMIT	0x22
#define	PCI_CFG_PRE_MEM_BASE	0x24
#define	PCI_CFG_PRE_MEM_LIMIT	0x26
#define	PCI_CFG_PRE_MEM_BASE_U	0x28
#define	PCI_CFG_PRE_MEM_LIMIT_U	0x2c
#define	PCI_CFG_IO_BASE_U	0x30
#define	PCI_CFG_IO_LIMIT_U	0x32
#define	PCI_CFG_ROM_BASE	0x38
#define	PCI_CFG_BRG_INT_LINE	0x3c
#define	PCI_CFG_BRG_INT_PIN	0x3d
#define	PCI_CFG_BRIDGE_CONTROL	0x3e


/***********************************************************************
 * 405GP PCI Master configuration.
 * Map one 512 MB range of PLB/processor addresses to PCI memory space.
 *   PLB address 0x80000000-0x9FFFFFFF ==> PCI address 0x80000000-0x9FFFFFFF
 *   Use byte reversed out routines to handle endianess.
 ***********************************************************************/
#define PCI_M0_LOCAL_ADDR			0x80000000
#define PCI_M0_PCI_LOW_ADDR		0x80000000
#define PCI_M0_PCI_HIGH_ADDR	0x00000000
#define PCI_M0_MASK_ATTRIB		0xE0000001  /* no prefetching, and enable region */
/**************************************************************************
 * Map one 512 MB range of PLB/processor addresses to PCI memory space.
 * PLB address 0xA0000000-0xBFFFFFFF ==> PCI address 0x00000000-0x1FFFFFFF
 * This space is for the VGA card.
 **************************************************************************/
#define PCI_M1_LOCAL_ADDR			0xA0000000
#define PCI_M1_PCI_LOW_ADDR		0x00000000
#define PCI_M1_PCI_HIGH_ADDR	0x00000000
#define PCI_M1_MASK_ATTRIB		0xE0000001  /* no prefetching, and enable region */
/***************************************************************************
 * PMM2 is not used.  Initialize them to zero.
 *****************************************************************************/
#define PCI_M2_LOCAL_ADDR			0x00000000
#define PCI_M2_PCI_LOW_ADDR		0x00000000
#define PCI_M2_PCI_HIGH_ADDR	0x00000000
#define PCI_M2_MASK_ATTRIB		0x00000000  /* not enabled */

typedef struct pciHeaderDevice
    {
    short	vendorId;	/* vendor ID */
    short	deviceId;	/* device ID */
    short	command;	/* command register */
    short	status;		/* status register */
    char	revisionId;	/* revision ID */
    char	classCode;	/* class code */
    char	subClass;	/* sub class code */
    char	progIf;		/* programming interface */
    char	cacheLine;	/* cache line */
    char	latency;	/* latency time */
    char	headerType;	/* header type */
    char	bist;		/* BIST */
    int		base0;		/* base address 0 */
    int		base1;		/* base address 1 */
    int		base2;		/* base address 2 */
    int		base3;		/* base address 3 */
    int		base4;		/* base address 4 */
    int		base5;		/* base address 5 */
    int		cis;		/* cardBus CIS pointer */
    short	subVendorId;	/* sub system vendor ID */
    short	subSystemId;	/* sub system ID */
    int		romBase;	/* expansion ROM base address */
    int		reserved0;	/* reserved */
    int		reserved1;	/* reserved */
    char	intLine;	/* interrupt line */
    char	intPin;		/* interrupt pin */
    char	minGrant;	/* min Grant */
    char	maxLatency;	/* max Latency */
    } PCI_HEADER_DEVICE;

typedef struct pciHeaderBridge
    {
    short	vendorId;	/* vendor ID */
    short	deviceId;	/* device ID */
    short	command;	/* command register */
    short	status;		/* status register */
    char	revisionId;	/* revision ID */
    char	classCode;	/* class code */
    char	subClass;	/* sub class code */
    char	progIf;		/* programming interface */
    char	cacheLine;	/* cache line */
    char	latency;	/* latency time */
    char	headerType;	/* header type */
    char	bist;		/* BIST */
    int		base0;		/* base address 0 */
    int		base1;		/* base address 1 */
    char	priBus;		/* primary bus number */
    char	secBus;		/* secondary bus number */
    char	subBus;		/* subordinate bus number */
    char	secLatency;	/* secondary latency timer */
    char	ioBase;		/* IO base */
    char	ioLimit;	/* IO limit */
    short	secStatus;	/* secondary status */
    short	memBase;	/* memory base */
    short	memLimit;	/* memory limit */
    short	preBase;	/* prefetchable memory base */
    short	preLimit;	/* prefetchable memory limit */
    int		preBaseUpper;	/* prefetchable memory base upper 32 bits */
    int		preLimitUpper;	/* prefetchable memory base upper 32 bits */
    short	ioBaseUpper;	/* IO base upper 16 bits */
    short	ioLimitUpper;	/* IO limit upper 16 bits */
    int		reserved;	/* reserved */
    int		romBase;	/* expansion ROM base address */
    char	intLine;	/* interrupt line */
    char	intPin;		/* interrupt pin */
    short	control;	/* bridge control */
    } PCI_HEADER_BRIDGE;


typedef struct pciRecourceDesc
	{
	unsigned long	BusDevFunc; /* location of the device */
	short	vendorId;		/* vendor ID */
	short	deviceId;		/* device ID */
  char	revisionId;	/* revision ID */
  char	classCode;	/* class code */
  char	subClass;		/* sub class code */
  char	progIf;		/* programming interface */
  char	headerType;	/* header type */
  unsigned long		size[MAX_PCI_BASE_REG];		/* memory sizes */
  char	attr[MAX_PCI_BASE_REG];		/* memory attributes */
  char	intLine;	/* interrupt line */
  char	intPin;		/* interrupt pin */
	char	pciInt; 	/* Pci Interrupt Line ( 0 = no, 1 = A...)*/
	} PCI_RESOURCE_DESC;


/* table fore PCI Initialization */
typedef struct {
	const int index;
	const unsigned long val;
	const int with;
} PCI_CFG_TABLE;



unsigned long    PCI_Read_CFG_Reg(int BusDevFunc, int Reg, int Width);
int  	PCI_Write_CFG_Reg(int BusDevFunc, int Reg, unsigned long Value, int Width);
void  PCI_Scan(int BusNum);
void  PCI_Config_Device(int BusDevFunc, int NumBaseAddr);
void  PCI_Config_VGA_Device(int BusDevFunc, int NumBaseAddr);
void  PCI_Config_Bridge(int BusDevFunc);
void  PCI_Dump_Device(int BusDevFunc);
int   PCI_Find_Device(unsigned short VendorID, unsigned short DeviceID);
void  pciHeaderShow(int BusDevFunc);
void  pciDheaderPrint(PCI_HEADER_DEVICE * pD);
void  pciBheaderPrint(PCI_HEADER_BRIDGE * pB);
void  PCI_Config_ISABridge(int BusDevFunc);
void  PCI_Config_VGA_contrl(int BusDevFunc);

void pciScanForDevices(int BusNum);
void pciShowRes(PCI_RESOURCE_DESC *pd);
int pciGetResource(PCI_RESOURCE_DESC * pR);
int pciGetHeader0(PCI_HEADER_DEVICE * pD,int BusDevFunc);


#endif
