⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 405gp_pci.c

📁 嵌入式ARM的一些源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*-----------------------------------------------------------------------------+
|
|       This source code has been made available to you by IBM on an AS-IS
|       basis.  Anyone receiving this source is licensed under IBM
|       copyrights to use it in any way he or she deems fit, including
|       copying it, modifying it, compiling it, and redistributing it either
|       with or without modifications.  No license under IBM patents or
|       patent applications is to be implied by the copyright license.
|
|       Any user of this software should understand that IBM cannot provide
|       technical support for this software and will not be responsible for
|       any consequences resulting from the use of this software.
|
|       Any person who transfers this source code or any derivative work
|       must include the IBM copyright notice, this paragraph, and the
|       preceding two paragraphs in the transferred software.
|
|       COPYRIGHT   I B M   CORPORATION 1995
|       LICENSED MATERIAL  -  PROGRAM PROPERTY OF I B M
+-----------------------------------------------------------------------------*/

#include <ppcboot.h>
#include <command.h>
#include <cmd_boot.h>
#include <405gp_pci.h>
#include <asm/processor.h>

#ifdef CONFIG_PPC405GP

#ifdef CONFIG_PCI_PNP

/*#define DEBUG*/

/*------------------------------------------------------------------------
| These are the lowest addresses allowed for PCI configuration.
| They correspond to lowest available I/O and Memory addresses.
| In the case where where multiple PMM regs are being used to map
| different PLB to PCI regions, each region should have it's own
| minimum address.
+-----------------------------------------------------------------------*/
unsigned long    LowestMemAddr1 = MIN_PCI_MEMADDR1;
unsigned long    LowestMemAddr2 = MIN_PCI_MEMADDR2;
unsigned long    LowestIOAddr   = MIN_PCI_PCI_IOADDR;

unsigned long    MaxBusNum = 0;

static __inline__ unsigned long get_msr(void)
{
    unsigned long msr;

    asm volatile("mfmsr %0" : "=r" (msr) :);
    return msr;
}

static __inline__ void set_msr(unsigned long msr)
{
    asm volatile("mtmsr %0" : : "r" (msr));
}


/*-----------------------------------------------------------------------------+
| pci_init.  Initializes the 405GP PCI Configuration regs.
+-----------------------------------------------------------------------------*/
void pci_init(void)
{
   unsigned short temp_short;

   /*--------------------------------------------------------------------------+
   | 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.
   +--------------------------------------------------------------------------*/
   out32r(PMM0MA,    0x00000000);        /* ensure disabled b4 setting PMM0LA */
   out32r(PMM0LA,    0x80000000);
   out32r(PMM0PCILA, 0x80000000);
   out32r(PMM0PCIHA, 0x00000000);
   out32r(PMM0MA,    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
   |   Use byte reversed out routines to handle endianess.
   | This space is for the VGA card.
   +--------------------------------------------------------------------------*/
   out32r(PMM1MA,    0x00000000);        /* ensure disabled b4 setting PMM1LA */
   out32r(PMM1LA,    0xA0000000);
   out32r(PMM1PCILA, 0x00000000);
   out32r(PMM1PCIHA, 0x00000000);
   out32r(PMM1MA,    0xE0000001);        /* no prefetching, and enable region */

   /*--------------------------------------------------------------------------+
   | PMM2 is not used.  Initialize them to zero.
   +--------------------------------------------------------------------------*/
   out32r(PMM2MA,    0x00000000);        /* ensure disabled b4 setting PMM2LA */
   out32r(PMM2LA,    0x00000000);
   out32r(PMM2PCILA, 0x00000000);
   out32r(PMM2PCIHA, 0x00000000);
   out32r(PMM2MA,    0x00000000);         /* not enabled */

   /*--------------------------------------------------------------------------+
   | 405GP PCI Target configuration.  (PTM1)
   | Map one 2 GB range of PCI addresses to PLB/processor address space.
   |   PCI address 0x00000000-0x7FFFFFFF ==> PLB address 0x00000000-0x7FFFFFFF
   |   The 0x00000008 default value of the 405GP PTM1 Base Address Register
   |   (in the PCI config header) is correct for this mapping.
   | Note: PTM1MS is hardwire enabled but we set the enable bit anyway.
   +--------------------------------------------------------------------------*/
   out32r(PTM1LA,    0x00000000);
   out32r(PTM1MS,    0x80000001);       /* 2GB, enable bit is hard-wired to 1 */

   /*--------------------------------------------------------------------------+
   | 405GP PCI Target configuration.  (PTM2) Not used here.
   | It is possible that the enable bit in PTM2MS could be set at power
   | up.  The ROM monitor only needs to use PTM1, so we must make sure that
   | PTM2 is disabled to avoid PCI target conflicts.
   | Note: PTM2MS must be enabled to write PTM 2 BAR.
   | Zero out PTM 2 BAR, then disable via PTM2MS.
   +--------------------------------------------------------------------------*/
   out32r(PTM2LA,    0x00000000);
   out32r(PTM2MS,    0x00000001);        /* set enable bit */
   PCI_Write_CFG_Reg(PCIDEVID_405GP, PCIBASEADDR2, 0x00000000, 4);
   out32r(PTM2MS,    0x00000000);        /* disable */

   /*--------------------------------------------------------------------------+
   | Write the 405GP PCI Configuration regs.
   |   Enable 405GP to be a master on the PCI bus (PMM).
   |   Enable 405GP to act as a PCI memory target (PTM).
   +--------------------------------------------------------------------------*/
   temp_short = PCI_Read_CFG_Reg(PCIDEVID_405GP, PCICMD, 2);
   PCI_Write_CFG_Reg(PCIDEVID_405GP, PCICMD, temp_short | BM_EN | MEM_EN, 2);

#if 0  /* test-only: no need yet! */
   /*--------------------------------------------------------------------------+
   | If PCI speed = 66Mhz, set 66Mhz capable bit.
   +--------------------------------------------------------------------------*/
   if (board_cfg.pci_speed==66666666) {
      temp_short = PCI_Read_CFG_Reg(PCIDEVID_405GP, PCISTATUS, 2);
      PCI_Write_CFG_Reg(PCIDEVID_405GP,PCISTATUS,(temp_short|CAPABLE_66MHZ), 2);
   }
#endif

#if 0  /* test-only: no need yet! */
   /*--------------------------------------------------------------------------+
   | Default value of the Bridge Options1 register is OK (0xFF60).
   | Default value of the Bridge Options2 register is OK (0x0100).
   | No need to change them in pass 2 405GP.
   | Low subsequent target latency timer values are not supported in pass 1.
   |      STLD = '1111' if asynchronous PCI
   |      STLD = '0111' if synchronous PCI
   +--------------------------------------------------------------------------*/
   /* The following should only be required for PASS 1 405GP because of       */
   /* errata #26                                                              */
   if (ppcMfpvr() == PVR_405GP_PASS1) 
     {
      temp_short = PCI_Read_CFG_Reg(PCIDEVID_405GP, PCIBRDGOPT2, 2);
      if (ppcMfstrap() & PCI_ASYNC_MODE_EN) {
        PCI_Write_CFG_Reg(PCIDEVID_405GP, PCIBRDGOPT2,(temp_short | 0x0F00), 2);
      }
      else {
        PCI_Write_CFG_Reg(PCIDEVID_405GP, PCIBRDGOPT2,(temp_short | 0x0700), 2);
      }
   }
#endif

   /*--------------------------------------------------------------------------+
   | Scan the PCI bus and configure devices found.
   +--------------------------------------------------------------------------*/
   PCI_Scan(0);

}

/*-----------------------------------------------------------------------------+
|  Subroutine:  PCI_Read_CFG_Reg
|  Description: Read a PCI configuration register
|  Inputs:
|               BusDevFunc      PCI Bus+Device+Function number
|               Reg             Configuration register number
|               Width           Number of bytes to read (1, 2, or 4)
|  Return value:
|               (unsigned int)  Value of the configuration register read.
|                      For reads shorter than 4 bytes, return value
|                      is LSB-justified
+-----------------------------------------------------------------------------*/
unsigned int     PCI_Read_CFG_Reg(int BusDevFunc, int Reg, int Width)
{
   unsigned int    RegAddr;

   /*--------------------------------------------------------------------------+
   | bit 31 must be 1 and bits 1:0 must be 0 (note Little Endian bit notation)
   +--------------------------------------------------------------------------*/
   RegAddr = 0x80000000 | ((Reg|BusDevFunc) & 0xFFFFFFFC);

   /*--------------------------------------------------------------------------+
   | Write reg to PCI Config Address
   +--------------------------------------------------------------------------*/
   out32r(PCICFGADR, RegAddr);

   /*--------------------------------------------------------------------------+
   | Read reg value from PCI Config Data
   +--------------------------------------------------------------------------*/
   switch (Width)
   {
      case 1: return ((unsigned int) in8(PCICFGDATA | (Reg & 0x3)));
      case 2: return ((unsigned int) in16r(PCICFGDATA | (Reg & 0x3)));
      case 4: return (in32r(PCICFGDATA | (Reg & 0x3)));
   }

   return 0; /* not reached: just to satisfy the compiler */
}

/*-----------------------------------------------------------------------------+
|  Subroutine:  PCI_Write_CFG_Reg
|  Description: Write a PCI configuration register.
|  Inputs:
|               BusDevFunc      PCI Bus+Device+Function number
|               Reg             Configuration register number
|               Value           Configuration register value
|               Width           Number of bytes to write (1, 2, or 4)
|  Return value:
|               0       Successful
| Updated for pass2 errata #6. Need to disable interrupts and clear the
| PCICFGADR reg after writing the PCICFGDATA reg.  
+-----------------------------------------------------------------------------*/
int    PCI_Write_CFG_Reg(int BusDevFunc, int Reg, unsigned int Value, int Width)
{
   unsigned int    RegAddr;
   unsigned int    msr;

   /*--------------------------------------------------------------------------+
   | Ensure interrupts disabled for pass2 errata #6.
   +--------------------------------------------------------------------------*/
   msr = get_msr();
   set_msr(msr & ~(MSR_EE|MSR_CE));

   /*--------------------------------------------------------------------------+
   | bit 31 must be 1 and bits 1:0 must be 0 (note Little Endian bit notation)
   +--------------------------------------------------------------------------*/
   RegAddr = 0x80000000 | ((Reg|BusDevFunc) & 0xFFFFFFFC);

   /*--------------------------------------------------------------------------+
   | Write reg to PCI Config Address
   +--------------------------------------------------------------------------*/
   out32r(PCICFGADR, RegAddr);

   /*--------------------------------------------------------------------------+
   | Write reg value to PCI Config Data
   +--------------------------------------------------------------------------*/
   switch (Width)
   {
      case 1: out8(PCICFGDATA | (Reg & 0x3), (unsigned char)(Value & 0xFF));
              break;
      case 2: out16r(PCICFGDATA | (Reg & 0x3),(unsigned short)(Value & 0xFFFF));
              break;
      case 4: out32r(PCICFGDATA | (Reg & 0x3), Value);
              break;
   }

   /*--------------------------------------------------------------------------+
   | Write PCI Config Address after writing PCICFGDATA for pass2 errata #6.
   +--------------------------------------------------------------------------*/
   out32r(PCICFGADR, 0x00000000);

   /*--------------------------------------------------------------------------+
   | Restore msr (for pass2 errata #6).
   +--------------------------------------------------------------------------*/
   set_msr(msr);

   return (0);
}

/*-----------------------------------------------------------------------
|
|  Subroutine:  PCI_Scan
|
|  Prototype:   void    PCI_Scan(int BusNum)
|
|  Description: Scan through all 16 allowable PCI IDs and configure
|               those for which the vendor ID indicates there is a
|               device present.
|
|  Inputs:
|               BusNum  Bus number where scanning begins
|
|  Return value:
|               None
|
+----------------------------------------------------------------------*/
void    PCI_Scan(int BusNum)
{
   int                     Device;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -