Reset monitor size back to 256 so environment can be written to flash on MPC85xx ADS and CDS releases. * Patch by Paolo Broggini, 02 Sep 2004: Make BSS clearing on ARM systems more robust * Patch by Yue Hu and Joe, 01 Sep 2004: - add PCI support for ixp425; - add EEPRO100 suppor tfor ixdp425 board. * Fix problem with protected sector detection in driver/cfi_flash.cmaster
parent
15c7a8efd2
commit
a1191902ca
@ -0,0 +1,613 @@ |
||||
/*
|
||||
* IXP PCI Init |
||||
* (C) Copyright 2004 eslab.whut.edu.cn |
||||
* Yue Hu(huyue_whut@yahoo.com.cn), Ligong Xue(lgxue@hotmail.com) |
||||
* |
||||
* 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 |
||||
*/ |
||||
|
||||
|
||||
#include <common.h> |
||||
|
||||
#ifdef CONFIG_PCI |
||||
|
||||
#include <asm/processor.h> |
||||
#include <asm/io.h> |
||||
#include <pci.h> |
||||
#include <asm/arch/ixp425.h> |
||||
#include <asm/arch/ixp425pci.h> |
||||
|
||||
static void non_prefetch_read (unsigned int addr, unsigned int cmd, |
||||
unsigned int *data); |
||||
static void non_prefetch_write (unsigned int addr, unsigned int cmd, |
||||
unsigned int data); |
||||
static void configure_pins (void); |
||||
static void sys_pci_gpio_clock_config (void); |
||||
static void pci_bus_scan (void); |
||||
static int pci_device_exists (unsigned int deviceNo); |
||||
static void sys_pci_bar_info_get (unsigned int devnum, unsigned int bus, |
||||
unsigned int dev, unsigned int func); |
||||
static void sys_pci_device_bars_write (void); |
||||
static void calc_bars (PciBar * Bars[], unsigned int nBars, |
||||
unsigned int startAddr); |
||||
|
||||
#define PCI_MEMORY_BUS 0x00000000 |
||||
#define PCI_MEMORY_PHY 0x48000000 |
||||
#define PCI_MEMORY_SIZE 0x04000000 |
||||
|
||||
#define PCI_MEM_BUS 0x40000000 |
||||
#define PCI_MEM_PHY 0x00000000 |
||||
#define PCI_MEM_SIZE 0x04000000 |
||||
|
||||
#define PCI_IO_BUS 0x40000000 |
||||
#define PCI_IO_PHY 0x50000000 |
||||
#define PCI_IO_SIZE 0x10000000 |
||||
|
||||
struct pci_controller hose; |
||||
|
||||
unsigned int nDevices; |
||||
unsigned int nMBars; |
||||
unsigned int nIOBars; |
||||
PciBar *memBars[IXP425_PCI_MAX_BAR]; |
||||
PciBar *ioBars[IXP425_PCI_MAX_BAR]; |
||||
PciDevice devices[IXP425_PCI_MAX_FUNC_ON_BUS]; |
||||
|
||||
extern void out_8 (volatile unsigned *addr, char val) |
||||
{ |
||||
*addr = val; |
||||
} |
||||
extern void out_le16 (volatile unsigned *addr, unsigned short val) |
||||
{ |
||||
*addr = cpu_to_le16 (val); |
||||
} |
||||
extern void out_le32 (volatile unsigned *addr, unsigned int val) |
||||
{ |
||||
*addr = cpu_to_le32 (val); |
||||
} |
||||
|
||||
extern unsigned char in_8 (volatile unsigned *addr) |
||||
{ |
||||
unsigned char val; |
||||
|
||||
val = *addr; |
||||
return val; |
||||
} |
||||
extern unsigned short in_le16 (volatile unsigned *addr) |
||||
{ |
||||
unsigned short val; |
||||
|
||||
val = *addr; |
||||
val = le16_to_cpu (val); |
||||
return val; |
||||
} |
||||
extern unsigned in_le32 (volatile unsigned *addr) |
||||
{ |
||||
unsigned int val; |
||||
|
||||
val = *addr; |
||||
val = le32_to_cpu (val); |
||||
return val; |
||||
} |
||||
|
||||
int pci_read_config_dword (pci_dev_t dev, int where, unsigned int *val) |
||||
{ |
||||
unsigned int retval; |
||||
unsigned int addr; |
||||
|
||||
/*address bits 31:28 specify the device 10:8 specify the function */ |
||||
/*Set the address to be read */ |
||||
addr = BIT ((31 - dev)) | (where & ~3); |
||||
non_prefetch_read (addr, NP_CMD_CONFIGREAD, &retval); |
||||
|
||||
*val = retval; |
||||
|
||||
return (OK); |
||||
} |
||||
|
||||
int pci_read_config_word (pci_dev_t dev, int where, unsigned short *val) |
||||
{ |
||||
unsigned int n; |
||||
unsigned int retval; |
||||
unsigned int addr; |
||||
unsigned int byteEnables; |
||||
|
||||
n = where % 4; |
||||
/*byte enables are 4 bits active low, the position of each
|
||||
bit maps to the byte that it enables */ |
||||
byteEnables = |
||||
(~(BIT (n) | BIT ((n + 1)))) & |
||||
IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK; |
||||
byteEnables = byteEnables << PCI_NP_CBE_BESL; |
||||
/*address bits 31:28 specify the device 10:8 specify the function */ |
||||
/*Set the address to be read */ |
||||
addr = BIT ((31 - dev)) | (where & ~3); |
||||
non_prefetch_read (addr, byteEnables | NP_CMD_CONFIGREAD, &retval); |
||||
|
||||
/*Pick out the word we are interested in */ |
||||
*val = (retval >> (8 * n)); |
||||
|
||||
return (OK); |
||||
} |
||||
|
||||
int pci_read_config_byte (pci_dev_t dev, int where, unsigned char *val) |
||||
{ |
||||
unsigned int retval; |
||||
unsigned int n; |
||||
unsigned int byteEnables; |
||||
unsigned int addr; |
||||
|
||||
n = where % 4; |
||||
/*byte enables are 4 bits, active low, the position of each
|
||||
bit maps to the byte that it enables */ |
||||
byteEnables = (~BIT (n)) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK; |
||||
byteEnables = byteEnables << PCI_NP_CBE_BESL; |
||||
|
||||
/*address bits 31:28 specify the device, 10:8 specify the function */ |
||||
/*Set the address to be read */ |
||||
addr = BIT ((31 - dev)) | (where & ~3); |
||||
non_prefetch_read (addr, byteEnables | NP_CMD_CONFIGREAD, &retval); |
||||
/*Pick out the byte we are interested in */ |
||||
*val = (retval >> (8 * n)); |
||||
|
||||
return (OK); |
||||
} |
||||
|
||||
int pci_write_config_byte (pci_dev_t dev, int where, unsigned char val) |
||||
{ |
||||
unsigned int addr; |
||||
unsigned int byteEnables; |
||||
unsigned int n; |
||||
unsigned int ldata; |
||||
|
||||
n = where % 4; |
||||
/*byte enables are 4 bits active low, the position of each
|
||||
bit maps to the byte that it enables */ |
||||
byteEnables = (~BIT (n)) & IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK; |
||||
byteEnables = byteEnables << PCI_NP_CBE_BESL; |
||||
ldata = val << (8 * n); |
||||
/*address bits 31:28 specify the device 10:8 specify the function */ |
||||
/*Set the address to be written */ |
||||
addr = BIT ((31 - dev)) | (where & ~3); |
||||
non_prefetch_write (addr, byteEnables | NP_CMD_CONFIGWRITE, ldata); |
||||
|
||||
return (OK); |
||||
} |
||||
|
||||
int pci_write_config_word (pci_dev_t dev, int where, unsigned short val) |
||||
{ |
||||
unsigned int addr; |
||||
unsigned int byteEnables; |
||||
unsigned int n; |
||||
unsigned int ldata; |
||||
|
||||
n = where % 4; |
||||
/*byte enables are 4 bits active low, the position of each
|
||||
bit maps to the byte that it enables */ |
||||
byteEnables = |
||||
(~(BIT (n) | BIT ((n + 1)))) & |
||||
IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK; |
||||
byteEnables = byteEnables << PCI_NP_CBE_BESL; |
||||
ldata = val << (8 * n); |
||||
/*address bits 31:28 specify the device 10:8 specify the function */ |
||||
/*Set the address to be written */ |
||||
addr = BIT (31 - dev) | (where & ~3); |
||||
non_prefetch_write (addr, byteEnables | NP_CMD_CONFIGWRITE, ldata); |
||||
|
||||
return (OK); |
||||
} |
||||
|
||||
int pci_write_config_dword (pci_dev_t dev, int where, unsigned int val) |
||||
{ |
||||
unsigned int addr; |
||||
|
||||
/*address bits 31:28 specify the device 10:8 specify the function */ |
||||
/*Set the address to be written */ |
||||
addr = BIT (31 - dev) | (where & ~3); |
||||
non_prefetch_write (addr, NP_CMD_CONFIGWRITE, val); |
||||
|
||||
return (OK); |
||||
} |
||||
|
||||
void non_prefetch_read (unsigned int addr, |
||||
unsigned int cmd, unsigned int *data) |
||||
{ |
||||
REG_WRITE (PCI_CSR_BASE, PCI_NP_AD_OFFSET, addr); |
||||
|
||||
/*set up and execute the read */ |
||||
REG_WRITE (PCI_CSR_BASE, PCI_NP_CBE_OFFSET, cmd); |
||||
|
||||
/*The result of the read is now in np_rdata */ |
||||
REG_READ (PCI_CSR_BASE, PCI_NP_RDATA_OFFSET, *data); |
||||
|
||||
return; |
||||
} |
||||
|
||||
void non_prefetch_write (unsigned int addr, |
||||
unsigned int cmd, unsigned int data) |
||||
{ |
||||
|
||||
REG_WRITE (PCI_CSR_BASE, PCI_NP_AD_OFFSET, addr); |
||||
/*set up the write */ |
||||
REG_WRITE (PCI_CSR_BASE, PCI_NP_CBE_OFFSET, cmd); |
||||
/*Execute the write by writing to NP_WDATA */ |
||||
REG_WRITE (PCI_CSR_BASE, PCI_NP_WDATA_OFFSET, data); |
||||
|
||||
return; |
||||
} |
||||
|
||||
/*
|
||||
* PCI controller config registers are accessed through these functions |
||||
* i.e. these allow us to set up our own BARs etc. |
||||
*/ |
||||
void crp_read (unsigned int offset, unsigned int *data) |
||||
{ |
||||
REG_WRITE (PCI_CSR_BASE, PCI_CRP_AD_CBE_OFFSET, offset); |
||||
REG_READ (PCI_CSR_BASE, PCI_CRP_RDATA_OFFSET, *data); |
||||
} |
||||
|
||||
void crp_write (unsigned int offset, unsigned int data) |
||||
{ |
||||
/*The CRP address register bit 16 indicates that we want to do a write */ |
||||
REG_WRITE (PCI_CSR_BASE, PCI_CRP_AD_CBE_OFFSET, |
||||
PCI_CRP_WRITE | offset); |
||||
REG_WRITE (PCI_CSR_BASE, PCI_CRP_WDATA_OFFSET, data); |
||||
} |
||||
|
||||
/*struct pci_controller *hose*/ |
||||
void pci_ixp_init (struct pci_controller *hose) |
||||
{ |
||||
unsigned int regval; |
||||
|
||||
hose->first_busno = 0; |
||||
hose->last_busno = 0x00; |
||||
|
||||
/* System memory space */ |
||||
pci_set_region (hose->regions + 0, |
||||
PCI_MEMORY_BUS, |
||||
PCI_MEMORY_PHY, PCI_MEMORY_SIZE, PCI_REGION_MEMORY); |
||||
|
||||
/* PCI memory space */ |
||||
pci_set_region (hose->regions + 1, |
||||
PCI_MEM_BUS, |
||||
PCI_MEM_PHY, PCI_MEM_SIZE, PCI_REGION_MEM); |
||||
/* PCI I/O space */ |
||||
pci_set_region (hose->regions + 2, |
||||
PCI_IO_BUS, PCI_IO_PHY, PCI_IO_SIZE, PCI_REGION_IO); |
||||
|
||||
hose->region_count = 3; |
||||
|
||||
pci_register_hose (hose); |
||||
|
||||
/*
|
||||
========================================================== |
||||
Init IXP PCI |
||||
========================================================== |
||||
*/ |
||||
REG_READ (PCI_CSR_BASE, PCI_CSR_OFFSET, regval); |
||||
regval |= 1 << 2; |
||||
REG_WRITE (PCI_CSR_BASE, PCI_CSR_OFFSET, regval); |
||||
|
||||
configure_pins (); |
||||
|
||||
READ_GPIO_REG (IXP425_GPIO_GPOUTR, regval); |
||||
WRITE_GPIO_REG (IXP425_GPIO_GPOUTR, regval & (~(1 << 13))); |
||||
udelay (533); |
||||
sys_pci_gpio_clock_config (); |
||||
REG_WRITE (PCI_CSR_BASE, PCI_INTEN_OFFSET, 0); |
||||
udelay (100); |
||||
READ_GPIO_REG (IXP425_GPIO_GPOUTR, regval); |
||||
WRITE_GPIO_REG (IXP425_GPIO_GPOUTR, regval | (1 << 13)); |
||||
udelay (533); |
||||
crp_write (PCI_CFG_BASE_ADDRESS_0, IXP425_PCI_BAR_0_DEFAULT); |
||||
crp_write (PCI_CFG_BASE_ADDRESS_1, IXP425_PCI_BAR_1_DEFAULT); |
||||
crp_write (PCI_CFG_BASE_ADDRESS_2, IXP425_PCI_BAR_2_DEFAULT); |
||||
crp_write (PCI_CFG_BASE_ADDRESS_3, IXP425_PCI_BAR_3_DEFAULT); |
||||
crp_write (PCI_CFG_BASE_ADDRESS_4, IXP425_PCI_BAR_4_DEFAULT); |
||||
crp_write (PCI_CFG_BASE_ADDRESS_5, IXP425_PCI_BAR_5_DEFAULT); |
||||
/*Setup PCI-AHB and AHB-PCI address mappings */ |
||||
REG_WRITE (PCI_CSR_BASE, PCI_AHBMEMBASE_OFFSET, |
||||
IXP425_PCI_AHBMEMBASE_DEFAULT); |
||||
|
||||
REG_WRITE (PCI_CSR_BASE, PCI_AHBIOBASE_OFFSET, |
||||
IXP425_PCI_AHBIOBASE_DEFAULT); |
||||
|
||||
REG_WRITE (PCI_CSR_BASE, PCI_PCIMEMBASE_OFFSET, |
||||
IXP425_PCI_PCIMEMBASE_DEFAULT); |
||||
|
||||
crp_write (PCI_CFG_SUB_VENDOR_ID, IXP425_PCI_SUB_VENDOR_SYSTEM); |
||||
|
||||
REG_READ (PCI_CSR_BASE, PCI_CSR_OFFSET, regval); |
||||
regval |= PCI_CSR_IC | PCI_CSR_ABE | PCI_CSR_PDS; |
||||
REG_WRITE (PCI_CSR_BASE, PCI_CSR_OFFSET, regval); |
||||
crp_write (PCI_CFG_COMMAND, PCI_CFG_CMD_MAE | PCI_CFG_CMD_BME); |
||||
udelay (1000); |
||||
|
||||
pci_write_config_word (0, PCI_CFG_COMMAND, INITIAL_PCI_CMD); |
||||
REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PSE |
||||
| PCI_ISR_PFE | PCI_ISR_PPE | PCI_ISR_AHBE); |
||||
#ifdef CONFIG_PCI_SCAN_SHOW |
||||
printf ("Device bus dev func deviceID vendorID \n"); |
||||
#endif |
||||
pci_bus_scan (); |
||||
} |
||||
|
||||
void configure_pins (void) |
||||
{ |
||||
unsigned int regval; |
||||
|
||||
/* Disable clock on GPIO PIN 14 */ |
||||
READ_GPIO_REG (IXP425_GPIO_GPCLKR, regval); |
||||
WRITE_GPIO_REG (IXP425_GPIO_GPCLKR, regval & (~(1 << 8))); |
||||
READ_GPIO_REG (IXP425_GPIO_GPCLKR, regval); |
||||
|
||||
READ_GPIO_REG (IXP425_GPIO_GPOER, regval); |
||||
WRITE_GPIO_REG (IXP425_GPIO_GPOER, |
||||
(((~(3 << 13)) & regval) | (0xf << 8))); |
||||
READ_GPIO_REG (IXP425_GPIO_GPOER, regval); |
||||
|
||||
READ_GPIO_REG (IXP425_GPIO_GPIT2R, regval); |
||||
WRITE_GPIO_REG (IXP425_GPIO_GPIT2R, |
||||
(regval & |
||||
((0x1 << 9) | (0x1 << 6) | (0x1 << 3) | 0x1))); |
||||
READ_GPIO_REG (IXP425_GPIO_GPIT2R, regval); |
||||
|
||||
READ_GPIO_REG (IXP425_GPIO_GPISR, regval); |
||||
WRITE_GPIO_REG (IXP425_GPIO_GPISR, (regval | (0xf << 8))); |
||||
READ_GPIO_REG (IXP425_GPIO_GPISR, regval); |
||||
} |
||||
|
||||
void sys_pci_gpio_clock_config (void) |
||||
{ |
||||
unsigned int regval; |
||||
|
||||
READ_GPIO_REG (IXP425_GPIO_GPCLKR, regval); |
||||
regval |= 0x1 << 4; |
||||
WRITE_GPIO_REG (IXP425_GPIO_GPCLKR, regval); |
||||
READ_GPIO_REG (IXP425_GPIO_GPCLKR, regval); |
||||
regval |= 0x1 << 8; |
||||
WRITE_GPIO_REG (IXP425_GPIO_GPCLKR, regval); |
||||
} |
||||
|
||||
void pci_bus_scan (void) |
||||
{ |
||||
unsigned int bus = 0, dev, func = 0; |
||||
unsigned short data16; |
||||
unsigned int data32; |
||||
unsigned char intPin; |
||||
|
||||
/* Assign first device to ourselves */ |
||||
devices[0].bus = 0; |
||||
devices[0].device = 0; |
||||
devices[0].func = 0; |
||||
|
||||
crp_read (PCI_CFG_VENDOR_ID, &data32); |
||||
|
||||
devices[0].vendor_id = data32 & IXP425_PCI_BOTTOM_WORD_OF_LONG_MASK; |
||||
devices[0].device_id = data32 >> 16; |
||||
devices[0].error = FALSE; |
||||
devices[0].bar[NO_BAR].size = 0; /*dummy - required */ |
||||
|
||||
nDevices = 1; |
||||
|
||||
nMBars = 0; |
||||
nIOBars = 0; |
||||
|
||||
for (dev = 0; dev < IXP425_PCI_MAX_DEV; dev++) { |
||||
|
||||
/*Check whether a device is present */ |
||||
if (pci_device_exists (dev) != TRUE) { |
||||
|
||||
/*Clear error bits in ISR, write 1 to clear */ |
||||
REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PSE |
||||
| PCI_ISR_PFE | PCI_ISR_PPE | |
||||
PCI_ISR_AHBE); |
||||
continue; |
||||
} |
||||
|
||||
/*A device is present, add an entry to the array */ |
||||
devices[nDevices].bus = bus; |
||||
devices[nDevices].device = dev; |
||||
devices[nDevices].func = func; |
||||
|
||||
pci_read_config_word (dev, PCI_CFG_VENDOR_ID, &data16); |
||||
|
||||
devices[nDevices].vendor_id = data16; |
||||
|
||||
pci_read_config_word (dev, PCI_CFG_DEVICE_ID, &data16); |
||||
devices[nDevices].device_id = data16; |
||||
|
||||
/*The device is functioning correctly, set error to FALSE */ |
||||
devices[nDevices].error = FALSE; |
||||
|
||||
/*Figure out what BARs are on this device */ |
||||
sys_pci_bar_info_get (nDevices, bus, dev, func); |
||||
/*Figure out what INTX# line the card uses */ |
||||
pci_read_config_byte (dev, PCI_CFG_DEV_INT_PIN, &intPin); |
||||
|
||||
/*assign the appropriate irq line */ |
||||
if (intPin > PCI_IRQ_LINES) { |
||||
devices[nDevices].error = TRUE; |
||||
} else if (intPin != 0) { |
||||
/*This device uses an interrupt line */ |
||||
/*devices[nDevices].irq = ixp425PciIntTranslate[dev][intPin-1]; */ |
||||
devices[nDevices].irq = intPin; |
||||
} |
||||
#ifdef CONFIG_PCI_SCAN_SHOW |
||||
printf ("%06d %03d %03d %04d %08d %08x\n", nDevices, |
||||
devices[nDevices].vendor_id); |
||||
#endif |
||||
nDevices++; |
||||
|
||||
} |
||||
|
||||
calc_bars (memBars, nMBars, IXP425_PCI_BAR_MEM_BASE); |
||||
sys_pci_device_bars_write (); |
||||
|
||||
REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PSE |
||||
| PCI_ISR_PFE | PCI_ISR_PPE | PCI_ISR_AHBE); |
||||
} |
||||
|
||||
void sys_pci_bar_info_get (unsigned int devnum, |
||||
unsigned int bus, |
||||
unsigned int dev, unsigned int func) |
||||
{ |
||||
unsigned int data32; |
||||
unsigned int tmp; |
||||
unsigned int size; |
||||
|
||||
pci_write_config_dword (devnum, |
||||
PCI_CFG_BASE_ADDRESS_0, IXP425_PCI_BAR_QUERY); |
||||
pci_read_config_dword (devnum, PCI_CFG_BASE_ADDRESS_0, &data32); |
||||
|
||||
devices[devnum].bar[0].address = (data32 & 1); |
||||
|
||||
if (data32 & 1) { |
||||
/* IO space */ |
||||
tmp = data32 & ~0x3; |
||||
size = ~(tmp - 1); |
||||
devices[devnum].bar[0].size = size; |
||||
|
||||
if (nIOBars < IXP425_PCI_MAX_BAR) { |
||||
ioBars[nIOBars++] = &devices[devnum].bar[0]; |
||||
} |
||||
} else { |
||||
/* Mem space */ |
||||
tmp = data32 & ~IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK; |
||||
size = ~(tmp - 1); |
||||
devices[devnum].bar[0].size = size; |
||||
|
||||
if (nMBars < IXP425_PCI_MAX_BAR) { |
||||
memBars[nMBars++] = &devices[devnum].bar[0]; |
||||
} else { |
||||
devices[devnum].error = TRUE; |
||||
} |
||||
|
||||
} |
||||
|
||||
devices[devnum].bar[1].size = 0; |
||||
} |
||||
|
||||
void sortBars (PciBar * Bars[], unsigned int nBars) |
||||
{ |
||||
unsigned int i, j; |
||||
PciBar *tmp; |
||||
|
||||
if (nBars == 0) { |
||||
return; |
||||
} |
||||
|
||||
/* Sort biggest to smallest */ |
||||
for (i = 0; i < nBars - 1; i++) { |
||||
for (j = i + 1; j < nBars; j++) { |
||||
if (Bars[j]->size > Bars[i]->size) { |
||||
/* swap them */ |
||||
tmp = Bars[i]; |
||||
Bars[i] = Bars[j]; |
||||
Bars[j] = tmp; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
void calc_bars (PciBar * Bars[], unsigned int nBars, unsigned int startAddr) |
||||
{ |
||||
unsigned int i; |
||||
|
||||
if (nBars == 0) { |
||||
return; |
||||
} |
||||
|
||||
for (i = 0; i < nBars; i++) { |
||||
Bars[i]->address |= startAddr; |
||||
startAddr += Bars[i]->size; |
||||
} |
||||
} |
||||
|
||||
void sys_pci_device_bars_write (void) |
||||
{ |
||||
unsigned int i; |
||||
int addr; |
||||
|
||||
for (i = 1; i < nDevices; i++) { |
||||
if (devices[i].error) { |
||||
continue; |
||||
} |
||||
|
||||
pci_write_config_dword (devices[i].device, |
||||
PCI_CFG_BASE_ADDRESS_0, |
||||
devices[i].bar[0].address); |
||||
addr = BIT (31 - |
||||
devices[i]. |
||||
device) | (0 << PCI_NP_AD_FUNCSL) | |
||||
(PCI_CFG_BASE_ADDRESS_0) & ~3; |
||||
pci_write_config_dword (devices[i].device, |
||||
PCI_CFG_DEV_INT_LINE, devices[i].irq); |
||||
|
||||
pci_write_config_word (devices[i].device, |
||||
PCI_CFG_COMMAND, INITIAL_PCI_CMD); |
||||
|
||||
} |
||||
} |
||||
|
||||
|
||||
int pci_device_exists (unsigned int deviceNo) |
||||
{ |
||||
unsigned int vendorId; |
||||
unsigned int regval; |
||||
|
||||
pci_read_config_dword (deviceNo, PCI_CFG_VENDOR_ID, &vendorId); |
||||
|
||||
/* There are two ways to find out an empty device.
|
||||
* 1. check Master Abort bit after the access. |
||||
* 2. check whether the vendor id read back is 0x0. |
||||
*/ |
||||
REG_READ (PCI_CSR_BASE, PCI_ISR_OFFSET, regval); |
||||
if ((vendorId != 0x0) && ((regval & PCI_ISR_PFE) == 0)) { |
||||
return TRUE; |
||||
} |
||||
/*no device present, make sure that the master abort bit is reset */ |
||||
|
||||
REG_WRITE (PCI_CSR_BASE, PCI_ISR_OFFSET, PCI_ISR_PFE); |
||||
return FALSE; |
||||
} |
||||
|
||||
pci_dev_t pci_find_devices (struct pci_device_id * ids, int devNo) |
||||
{ |
||||
unsigned int i; |
||||
unsigned int devdidvid; |
||||
unsigned int didvid; |
||||
unsigned int vendorId, deviceId; |
||||
|
||||
vendorId = ids->vendor; |
||||
deviceId = ids->device; |
||||
didvid = ((deviceId << 16) & IXP425_PCI_TOP_WORD_OF_LONG_MASK) | |
||||
(vendorId & IXP425_PCI_BOTTOM_WORD_OF_LONG_MASK); |
||||
|
||||
for (i = devNo + 1; i < nDevices; i++) { |
||||
|
||||
pci_read_config_dword (devices[i].device, PCI_CFG_VENDOR_ID, |
||||
&devdidvid); |
||||
|
||||
if (devdidvid == didvid) { |
||||
return devices[i].device; |
||||
} |
||||
} |
||||
return -1; |
||||
} |
||||
#endif /* CONFIG_PCI */ |
@ -0,0 +1,312 @@ |
||||
/*
|
||||
* IXP PCI Init |
||||
* (C) Copyright 2004 eslab.whut.edu.cn |
||||
* Yue Hu(huyue_whut@yahoo.com.cn), Ligong Xue(lgxue@hotmail.com) |
||||
* |
||||
* 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 _IXP425PCI_H_ |
||||
#define _IXP425PCI_H_ |
||||
|
||||
#define TRUE 1 |
||||
#define FALSE 0 |
||||
#define OK 0 |
||||
#define ERROR -1 |
||||
#define BOOL int |
||||
|
||||
#define IXP425_PCI_MAX_BAR_PER_FUNC 6 |
||||
#define IXP425_PCI_MAX_BAR (IXP425_PCI_MAX_BAR_PER_FUNC * \ |
||||
IXP425_PCI_MAX_FUNC_ON_BUS) |
||||
|
||||
enum PciBarId |
||||
{ |
||||
CSR_BAR=0, |
||||
IO_BAR, |
||||
SD_BAR, |
||||
NO_BAR |
||||
}; |
||||
|
||||
/*Base address register descriptor*/ |
||||
typedef struct |
||||
{ |
||||
unsigned int size; |
||||
unsigned int address; |
||||
} PciBar; |
||||
|
||||
typedef struct |
||||
{ |
||||
unsigned int bus; |
||||
unsigned int device; |
||||
unsigned int func; |
||||
unsigned int irq; |
||||
BOOL error; |
||||
unsigned short vendor_id; |
||||
unsigned short device_id; |
||||
/*We need an extra entry in this array for dummy placeholder*/ |
||||
PciBar bar[IXP425_PCI_MAX_BAR_PER_FUNC + 1]; |
||||
} PciDevice; |
||||
|
||||
/* Mask definitions*/ |
||||
#define IXP425_PCI_TOP_WORD_OF_LONG_MASK 0xffff0000 |
||||
#define IXP425_PCI_TOP_BYTE_OF_LONG_MASK 0xff000000 |
||||
#define IXP425_PCI_BOTTOM_WORD_OF_LONG_MASK 0x0000ffff |
||||
#define IXP425_PCI_BOTTOM_TRIBYTES_OF_LONG_MASK 0x00ffffff |
||||
#define IXP425_PCI_BOTTOM_NIBBLE_OF_LONG_MASK 0x0000000f |
||||
#define IXP425_PCI_MAX_UINT32 0xffffffff |
||||
|
||||
|
||||
#define IXP425_PCI_BAR_QUERY 0xffffffff |
||||
|
||||
#define IXP425_PCI_BAR_MEM_BASE 0x100000 |
||||
#define IXP425_PCI_BAR_IO_BASE 0x000000 |
||||
|
||||
/*define the maximum number of bus segments - we support a single segment*/ |
||||
#define IXP425_PCI_MAX_BUS 1 |
||||
/*define the maximum number of cards per bus segment*/ |
||||
#define IXP425_PCI_MAX_DEV 4 |
||||
/*define the maximum number of functions per device*/ |
||||
#define IXP425_PCI_MAX_FUNC 8 |
||||
/* define the maximum number of separate functions that we can
|
||||
potentially have on the bus*/ |
||||
#define IXP425_PCI_MAX_FUNC_ON_BUS (1+ IXP425_PCI_MAX_FUNC * \ |
||||
IXP425_PCI_MAX_DEV * \
|
||||
IXP425_PCI_MAX_BUS) |
||||
/*define the maximum number of BARs per function*/ |
||||
#define IXP425_PCI_MAX_BAR_PER_FUNC 6 |
||||
#define IXP425_PCI_MAX_BAR (IXP425_PCI_MAX_BAR_PER_FUNC * \ |
||||
IXP425_PCI_MAX_FUNC_ON_BUS) |
||||
|
||||
#define PCI_NP_CBE_BESL (4) |
||||
#define PCI_NP_AD_FUNCSL (8) |
||||
|
||||
#define REG_WRITE(b,o,v) (*(volatile unsigned int*)((b+o))=(v)) |
||||
#define REG_READ(b,o,v) ((v)=(*(volatile unsigned int*)((b+o)))) |
||||
|
||||
#define PCI_DELAY 500 |
||||
#define USEC_LOOP_COUNT 533 |
||||
#define PCI_SETTLE_USEC 200 |
||||
#define PCI_MIN_RESET_ASSERT_USEC 2000 |
||||
|
||||
/*Register addressing definitions for PCI controller configuration
|
||||
and status registers*/ |
||||
|
||||
#define PCI_CSR_BASE (0xC0000000) |
||||
/*
|
||||
#define PCI_NP_AD_OFFSET (0x00) |
||||
#define PCI_NP_CBE_OFFSET (0x04) |
||||
#define PCI_NP_WDATA_OFFSET (0x08) |
||||
#define PCI_NP_RDATA_OFFSET (0x0C) |
||||
#define PCI_CRP_OFFSET (0x10) |
||||
#define PCI_CRP_WDATA_OFFSET (0x14) |
||||
#define PCI_CRP_RDATA_OFFSET (0x18) |
||||
#define PCI_CSR_OFFSET (0x1C) |
||||
#define PCI_ISR_OFFSET (0x20) |
||||
#define PCI_INTEN_OFFSET (0x24) |
||||
#define PCI_DMACTRL_OFFSET (0x28) |
||||
#define PCI_AHBMEMBASE_OFFSET (0x2C) |
||||
#define PCI_AHBIOBASE_OFFSET (0x30) |
||||
#define PCI_PCIMEMBASE_OFFSET (0x34) |
||||
#define PCI_AHBDOORBELL_OFFSET (0x38) |
||||
#define PCI_PCIDOORBELL_OFFSET (0x3C) |
||||
#define PCI_ATPDMA0_AHBADDR (0x40) |
||||
#define PCI_ATPDMA0_PCIADDR (0x44) |
||||
#define PCI_ATPDMA0_LENADDR (0x48) |
||||
#define PCI_ATPDMA1_AHBADDR (0x4C) |
||||
#define PCI_ATPDMA1_PCIADDR (0x50) |
||||
#define PCI_ATPDMA1_LENADDR (0x54) |
||||
#define PCI_PTADMA0_AHBADDR (0x58) |
||||
#define PCI_PTADMA0_PCIADDR (0x5C) |
||||
#define PCI_PTADMA0_LENADDR (0x60) |
||||
#define PCI_PTADMA1_AHBADDR (0x64) |
||||
#define PCI_PTADMA1_PCIADDR (0x68) |
||||
#define PCI_PTADMA1_LENADDR (0x6C) |
||||
*/ |
||||
/*Non prefetch registers bit definitions*/ |
||||
/*
|
||||
#define NP_CMD_INTACK (0x0) |
||||
#define NP_CMD_SPECIAL (0x1) |
||||
#define NP_CMD_IOREAD (0x2) |
||||
#define NP_CMD_IOWRITE (0x3) |
||||
#define NP_CMD_MEMREAD (0x6) |
||||
#define NP_CMD_MEMWRITE (0x7) |
||||
#define NP_CMD_CONFIGREAD (0xa) |
||||
#define NP_CMD_CONFIGWRITE (0xb) |
||||
*/ |
||||
|
||||
/*define the default setting of the AHB memory base reg*/ |
||||
#define IXP425_PCI_AHBMEMBASE_DEFAULT 0x00010203 |
||||
#define IXP425_PCI_AHBIOBASE_DEFAULT 0x0 |
||||
#define IXP425_PCI_PCIMEMBASE_DEFAULT 0x0 |
||||
|
||||
/*define the default settings for the controller's BARs*/ |
||||
#ifdef IXP425_PCI_SIMPLE_MAPPING |
||||
#define IXP425_PCI_BAR_0_DEFAULT 0x00000000 |
||||
#define IXP425_PCI_BAR_1_DEFAULT 0x01000000 |
||||
#define IXP425_PCI_BAR_2_DEFAULT 0x02000000 |
||||
#define IXP425_PCI_BAR_3_DEFAULT 0x03000000 |
||||
#define IXP425_PCI_BAR_4_DEFAULT 0x00000000 |
||||
#define IXP425_PCI_BAR_5_DEFAULT 0x00000000 |
||||
#else |
||||
#define IXP425_PCI_BAR_0_DEFAULT 0x40000000 |
||||
#define IXP425_PCI_BAR_1_DEFAULT 0x41000000 |
||||
#define IXP425_PCI_BAR_2_DEFAULT 0x42000000 |
||||
#define IXP425_PCI_BAR_3_DEFAULT 0x43000000 |
||||
#define IXP425_PCI_BAR_4_DEFAULT 0x00000000 |
||||
#define IXP425_PCI_BAR_5_DEFAULT 0x00000000 |
||||
#endif |
||||
|
||||
/*Configuration Port register bit definitions*/ |
||||
#define PCI_CRP_WRITE BIT(16) |
||||
|
||||
/*ISR (Interrupt status) Register bit definitions*/ |
||||
#define PCI_ISR_PSE BIT(0) |
||||
#define PCI_ISR_PFE BIT(1) |
||||
#define PCI_ISR_PPE BIT(2) |
||||
#define PCI_ISR_AHBE BIT(3) |
||||
#define PCI_ISR_APDC BIT(4) |
||||
#define PCI_ISR_PADC BIT(5) |
||||
#define PCI_ISR_ADB BIT(6) |
||||
#define PCI_ISR_PDB BIT(7) |
||||
|
||||
/*INTEN (Interrupt Enable) Register bit definitions*/ |
||||
#define PCI_INTEN_PSE BIT(0) |
||||
#define PCI_INTEN_PFE BIT(1) |
||||
#define PCI_INTEN_PPE BIT(2) |
||||
#define PCI_INTEN_AHBE BIT(3) |
||||
#define PCI_INTEN_APDC BIT(4) |
||||
#define PCI_INTEN_PADC BIT(5) |
||||
#define PCI_INTEN_ADB BIT(6) |
||||
#define PCI_INTEN_PDB BIT(7) |
||||
|
||||
/*PCI configuration regs.*/ |
||||
|
||||
#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_VENDOR_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 |
||||
|
||||
/*Specify the initial command we send to PCI devices*/ |
||||
#define INITIAL_PCI_CMD (PCI_CMD_IO_ENABLE \ |
||||
| PCI_CMD_MEM_ENABLE \
|
||||
| PCI_CMD_MASTER_ENABLE \
|
||||
| PCI_CMD_WI_ENABLE) |
||||
|
||||
/*define the sub vendor and subsystem to be used */ |
||||
#define IXP425_PCI_SUB_VENDOR_SYSTEM 0x00000000 |
||||
|
||||
#define PCI_IRQ_LINES 4 |
||||
|
||||
#define PCI_CMD_IO_ENABLE 0x0001 /* IO access enable */ |
||||
#define PCI_CMD_MEM_ENABLE 0x0002 /* memory access enable */ |
||||
#define PCI_CMD_MASTER_ENABLE 0x0004 /* bus master enable */ |
||||
#define PCI_CMD_MON_ENABLE 0x0008 /* monitor special cycles enable */ |
||||
#define PCI_CMD_WI_ENABLE 0x0010 /* write and invalidate enable */ |
||||
#define PCI_CMD_SNOOP_ENABLE 0x0020 /* palette snoop enable */ |
||||
#define PCI_CMD_PERR_ENABLE 0x0040 /* parity error enable */ |
||||
#define PCI_CMD_WC_ENABLE 0x0080 /* wait cycle enable */ |
||||
#define PCI_CMD_SERR_ENABLE 0x0100 /* system error enable */ |
||||
#define PCI_CMD_FBTB_ENABLE 0x0200 /* fast back to back enable */ |
||||
|
||||
|
||||
/*CSR Register bit definitions*/ |
||||
#define PCI_CSR_HOST BIT(0) |
||||
#define PCI_CSR_ARBEN BIT(1) |
||||
#define PCI_CSR_ADS BIT(2) |
||||
#define PCI_CSR_PDS BIT(3) |
||||
#define PCI_CSR_ABE BIT(4) |
||||
#define PCI_CSR_DBT BIT(5) |
||||
#define PCI_CSR_ASE BIT(8) |
||||
#define PCI_CSR_IC BIT(15) |
||||
|
||||
/*Configuration command bit definitions*/ |
||||
#define PCI_CFG_CMD_IOAE BIT(0) |
||||
#define PCI_CFG_CMD_MAE BIT(1) |
||||
#define PCI_CFG_CMD_BME BIT(2) |
||||
#define PCI_CFG_CMD_MWIE BIT(4) |
||||
#define PCI_CFG_CMD_SER BIT(8) |
||||
#define PCI_CFG_CMD_FBBE BIT(9) |
||||
#define PCI_CFG_CMD_MDPE BIT(24) |
||||
#define PCI_CFG_CMD_STA BIT(27) |
||||
#define PCI_CFG_CMD_RTA BIT(28) |
||||
#define PCI_CFG_CMD_RMA BIT(29) |
||||
#define PCI_CFG_CMD_SSE BIT(30) |
||||
#define PCI_CFG_CMD_DPE BIT(31) |
||||
|
||||
/*DMACTRL DMA Control and status Register*/ |
||||
#define PCI_DMACTRL_APDCEN BIT(0) |
||||
#define PCI_DMACTRL_APDC0 BIT(4) |
||||
#define PCI_DMACTRL_APDE0 BIT(5) |
||||
#define PCI_DMACTRL_APDC1 BIT(6) |
||||
#define PCI_DMACTRL_APDE1 BIT(7) |
||||
#define PCI_DMACTRL_PADCEN BIT(8) |
||||
#define PCI_DMACTRL_PADC0 BIT(12) |
||||
#define PCI_DMACTRL_PADE0 BIT(13) |
||||
#define PCI_DMACTRL_PADC1 BIT(14) |
||||
#define PCI_DMACTRL_PADE1 BIT(15) |
||||
|
||||
/* GPIO related register */ |
||||
#undef IXP425_GPIO_GPOUTR |
||||
#undef IXP425_GPIO_GPOER |
||||
#undef IXP425_GPIO_GPINR |
||||
#undef IXP425_GPIO_GPISR |
||||
#undef IXP425_GPIO_GPIT1R |
||||
#undef IXP425_GPIO_GPIT2R |
||||
#undef IXP425_GPIO_GPCLKR |
||||
|
||||
#define IXP425_GPIO_GPOUTR 0xC8004000 |
||||
#define IXP425_GPIO_GPOER 0xC8004004 |
||||
#define IXP425_GPIO_GPINR 0xC8004008 |
||||
#define IXP425_GPIO_GPISR 0xC800400C |
||||
#define IXP425_GPIO_GPIT1R 0xC8004010 |
||||
#define IXP425_GPIO_GPIT2R 0xC8004014 |
||||
#define IXP425_GPIO_GPCLKR 0xC8004018 |
||||
|
||||
#define READ_GPIO_REG(addr,val) \ |
||||
(val) = *((volatile int *)(addr)); |
||||
#define WRITE_GPIO_REG(addr,val) \ |
||||
*((volatile int *)(addr)) = (val); |
||||
|
||||
#endif |
Loading…
Reference in new issue