summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/leon2/pci/pci.c
diff options
context:
space:
mode:
authorDaniel Hellstrom <daniel@gaisler.com>2011-12-16 14:10:57 +0100
committerDaniel Hellstrom <daniel@gaisler.com>2015-04-17 01:10:17 +0200
commit46e41c98b30e9084e8a706129a78327da27c22a4 (patch)
tree5101111e5fc61a31cabf9c1370a06aa98051f7ae /c/src/lib/libbsp/sparc/leon2/pci/pci.c
parentLEON3: new Console driver, APBUART driver using Driver Manager (diff)
downloadrtems-46e41c98b30e9084e8a706129a78327da27c22a4.tar.bz2
LEON: replaced old BSP PCI layer with new generic libpci PCI layer
The old code used a limited PCI configuration library, which was duplicated into LEON2 and LEON3 BSP pci.c together with respective Host controller PCI interface. The LEON2 BSP had support for AT697 PCI, and LEON3 for GRPCI PCI Host controller. With this update new PCI Host drivers are added, and all support the new generic PCI Library: * AT697 PCI (LEON2 only) * GRPCI (LEON2-GRLIB and LEON3) * GRPCI2 (LEON2-GRLIB and LEON3) * Actel PCIF GRLIB Wrapper (LEON3 only) The LEON2 BSP is defined as big-endian PCI in bsp.h, since the AT697 supports only big-endian PCI.
Diffstat (limited to 'c/src/lib/libbsp/sparc/leon2/pci/pci.c')
-rw-r--r--c/src/lib/libbsp/sparc/leon2/pci/pci.c730
1 files changed, 0 insertions, 730 deletions
diff --git a/c/src/lib/libbsp/sparc/leon2/pci/pci.c b/c/src/lib/libbsp/sparc/leon2/pci/pci.c
deleted file mode 100644
index bf1cd32def..0000000000
--- a/c/src/lib/libbsp/sparc/leon2/pci/pci.c
+++ /dev/null
@@ -1,730 +0,0 @@
-/**
- * @file
- * @ingroup sparc_leon2
- * @brief Basic PCI Io functions
- */
-
-/*
- * pci.c : this file contains basic PCI Io functions.
- *
- * Copyright (C) 1999 valette@crf.canon.fr
- *
- * This code is heavily inspired by the public specification of STREAM V2
- * that can be found at :
- *
- * <http://www.chorus.com/Documentation/index.html> by following
- * the STREAM API Specification Document link.
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- *
- * Till Straumann, <strauman@slac.stanford.edu>, 1/2002
- * - separated bridge detection code out of this file
- *
- * Adapted to LEON2 AT697 PCI
- * Copyright (C) 2006 Gaisler Research
- *
- */
-
-#include <pci.h>
-#include <rtems/bspIo.h>
-#include <stdlib.h>
-
-/* Define PCI_INFO to get a listing of configured devices at boot time */
-#define PCI_INFO 1
-
-/* #define DEBUG 1 */
-
-#ifdef DEBUG
-#define DBG(x...) printk(x)
-#else
-#define DBG(x...)
-#endif
-
-/* allow for overriding these definitions */
-#ifndef PCI_CONFIG_ADDR
-#define PCI_CONFIG_ADDR 0xcf8
-#endif
-#ifndef PCI_CONFIG_DATA
-#define PCI_CONFIG_DATA 0xcfc
-#endif
-
-/* define a shortcut */
-#define pci BSP_pci_configuration
-
-/*
- * Bit encode for PCI_CONFIG_HEADER_TYPE register
- */
-unsigned char ucMaxPCIBus;
-
-typedef struct {
- /* 0x80000100 - PCI Device identification register 1 */
- volatile unsigned int pciid1;
- /* 0x80000104 - PCI Status & Command */
- volatile unsigned int pcisc;
- /* 0x80000108 - PCI Device identification register 2 */
- volatile unsigned int pciid2;
- /* 0x8000010c - BIST, Header type, Cache line size register */
- volatile unsigned int pcibhlc;
- /* 0x80000110 - Memory Base Address Register 1 */
- volatile unsigned int mbar1;
- /* 0x80000114 - Memory Base Address Register 2 */
- volatile unsigned int mbar2;
- /* 0x80000118 - IO Base Address Register 3 */
- volatile unsigned int iobar3;
- /* 0x8000011c - 0x80000128 */
- volatile unsigned int dummy1[4];
- /* 0x8000012c - Subsystem identification register */
- volatile unsigned int pcisid;
- /* 0x80000130 */
- volatile unsigned int dummy2;
- /* 0x80000134 - PCI capabilities pointer register */
- volatile unsigned int pcicp;
- /* 0x80000138 */
- volatile unsigned int dummy3;
- /* 0x8000013c - PCI latency interrupt register */
- volatile unsigned int pcili;
- /* 0x80000140 - PCI retry, trdy config */
- volatile unsigned int pcirt;
- /* 0x80000144 - PCI configuration write register */
- volatile unsigned int pcicw;
- /* 0x80000148 - PCI Initiator Start Address */
- volatile unsigned int pcisa;
- /* 0x8000014c - PCI Initiator Write Register */
- volatile unsigned int pciiw;
- /* 0x80000150 - PCI DMA configuration register */
- volatile unsigned int pcidma;
- /* 0x80000154 - PCI Initiator Status Register */
- volatile unsigned int pciis;
- /* 0x80000158 - PCI Initiator Configuration */
- volatile unsigned int pciic;
- /* 0x8000015c - PCI Target Page Address Register */
- volatile unsigned int pcitpa;
- /* 0x80000160 - PCI Target Status-Command Register */
- volatile unsigned int pcitsc;
- /* 0x80000164 - PCI Interrupt Enable Register */
- volatile unsigned int pciite;
- /* 0x80000168 - PCI Interrupt Pending Register */
- volatile unsigned int pciitp;
- /* 0x8000016c - PCI Interrupt Force Register */
- volatile unsigned int pciitf;
- /* 0x80000170 - PCI Data Register */
- volatile unsigned int pcid;
- /* 0x80000174 - PCI Burst End Register */
- volatile unsigned int pcibe;
- /* 0x80000178 - PCI DMA Address Register */
- volatile unsigned int pcidmaa;
-} AT697_PCI_Map;
-
-AT697_PCI_Map *pcic = (AT697_PCI_Map *) 0x80000100;
-
-#define PCI_MEM_START 0xa0000000
-#define PCI_MEM_END 0xf0000000
-#define PCI_MEM_SIZE (PCI_MEM_START - PCI_MEM_END)
-
-
-struct pci_res {
- unsigned int size;
- unsigned char bar;
- unsigned char devfn;
-};
-
-/* The configuration access functions uses the DMA functionality of the
- * AT697 pci controller to be able access all slots
- */
-
-static int
-BSP_pci_read_config_dword(unsigned char bus, unsigned char slot,
- unsigned char function, unsigned char offset, uint32_t *val) {
-
- volatile uint32_t data;
-
- if (offset & 3) return PCIBIOS_BAD_REGISTER_NUMBER;
-
- pcic->pciitp = 0xff; /* clear interrupts */
-
- pcic->pcisa = ( 1<<(11+slot) ) | ((function & 7)<<8) | (offset&0x3f);
- pcic->pcidma = 0xa01;
- pcic->pcidmaa = (unsigned int) &data;
-
- while (pcic->pciitp == 0)
- ;
-
- pcic->pciitp = 0xff; /* clear interrupts */
-
- if (pcic->pcisc & 0x20000000) { /* Master Abort */
- pcic->pcisc |= 0x20000000;
- *val = 0xffffffff;
- }
- else
- *val = data;
-
- DBG("pci_read - bus: %d, dev: %d, fn: %d, off: %d => addr: %x, val: %x\n",
- bus, slot, function, offset,
- (1<<(11+slot) ) | ((function & 7)<<8) | (offset&0x3f), *val);
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int
-BSP_pci_read_config_word(unsigned char bus, unsigned char slot,
- unsigned char function, unsigned char offset, unsigned short *val) {
- uint32_t v;
-
- if (offset & 1) return PCIBIOS_BAD_REGISTER_NUMBER;
-
- pci_read_config_dword(bus, slot, function, offset&~3, &v);
- *val = 0xffff & (v >> (8*(offset & 3)));
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int
-BSP_pci_read_config_byte(unsigned char bus, unsigned char slot,
- unsigned char function, unsigned char offset, unsigned char *val) {
- uint32_t v;
-
- pci_read_config_dword(bus, slot, function, offset&~3, &v);
-
- *val = 0xff & (v >> (8*(offset & 3)));
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int
-BSP_pci_write_config_dword(unsigned char bus, unsigned char slot,
- unsigned char function, unsigned char offset, uint32_t val) {
-
- if (offset & 3) return PCIBIOS_BAD_REGISTER_NUMBER;
-
- pcic->pciitp = 0xff; /* clear interrupts */
-
- pcic->pcisa = ( 1<<(11+slot) ) | ((function & 7)<<8) | (offset&0x3f);
- pcic->pcidma = 0xb01;
- pcic->pcidmaa = (unsigned int) &val;
-
- while (pcic->pciitp == 0)
- ;
-
- if (pcic->pcisc & 0x20000000) { /* Master Abort */
- pcic->pcisc |= 0x20000000;
- }
-
- pcic->pciitp = 0xff; /* clear interrupts */
-
-/* DBG("pci write - bus: %d, dev: %d, fn: %d, off: %d => addr: %x, val: %x\n",
- bus, slot, function, offset,
- (1<<(11+slot) ) | ((function & 7)<<8) | (offset&0x3f), val); */
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-
-static int
-BSP_pci_write_config_word(unsigned char bus, unsigned char slot,
- unsigned char function, unsigned char offset, unsigned short val) {
- uint32_t v;
-
- if (offset & 1) return PCIBIOS_BAD_REGISTER_NUMBER;
-
- pci_read_config_dword(bus, slot, function, offset&~3, &v);
-
- v = (v & ~(0xffff << (8*(offset&3)))) | ((0xffff&val) << (8*(offset&3)));
-
- return pci_write_config_dword(bus, slot, function, offset&~3, v);
-}
-
-
-static int
-BSP_pci_write_config_byte(unsigned char bus, unsigned char slot,
- unsigned char function, unsigned char offset, unsigned char val) {
- uint32_t v;
-
- pci_read_config_dword(bus, slot, function, offset&~3, &v);
-
- v = (v & ~(0xff << (8*(offset&3)))) | ((0xff&val) << (8*(offset&3)));
-
- return pci_write_config_dword(bus, slot, function, offset&~3, v);
-}
-
-
-
-const pci_config_access_functions pci_access_functions = {
- BSP_pci_read_config_byte,
- BSP_pci_read_config_word,
- BSP_pci_read_config_dword,
- BSP_pci_write_config_byte,
- BSP_pci_write_config_word,
- BSP_pci_write_config_dword
-};
-
-rtems_pci_config_t BSP_pci_configuration = {
- (volatile unsigned char*)PCI_CONFIG_ADDR,
- (volatile unsigned char*)PCI_CONFIG_DATA,
- &pci_access_functions
-};
-
-
-static void init_at697_pci(void) {
-
- /* Reset */
- pcic->pciic = 0xffffffff;
-
- /* Map system RAM at pci address 0x40000000
- and system SDRAM to pci address 0x60000000 */
- pcic->mbar1 = 0x40000000;
- pcic->mbar2 = 0x60000000;
- pcic->pcitpa = 0x40006000;
-
- /* Enable PCI master and target memory command response */
- pcic->pcisc |= 0x40 | 0x6;
-
- /* Set latency timer to 64 */
- pcic->pcibhlc = 0x00004000;
-
- /* Set Inititator configuration so that AHB slave accesses
- generate memory read/write commands */
- pcic->pciic = 0x41;
-
- pcic->pciite = 0xff;
-
-}
-
-/* May not pass a 1k boundary */
-static int dma_from_pci_1k(
- unsigned int addr, unsigned int paddr, unsigned char len) {
-
- int retval = 0;
-
- if (addr & 3) {
- return -1;
- }
-
- pcic->pciitp = 0xff; /* clear interrupts */
-
- pcic->pcisa = paddr;
- pcic->pcidma = 0xc00 | len;
- pcic->pcidmaa = addr;
-
- while (pcic->pciitp == 0)
- ;
-
- if (pcic->pciitp & 0x7F) {
- retval = -1;
- }
-
- pcic->pciitp = 0xff; /* clear interrupts */
-
- if (pcic->pcisc & 0x20000000) { /* Master Abort */
- pcic->pcisc |= 0x20000000;
- retval = -1;
- }
-
- return retval;
-}
-
-/* May not pass a 1k boundary */
-static int dma_to_pci_1k(
- unsigned int addr, unsigned int paddr, unsigned char len) {
-
- int retval = 0;
-
- if (addr & 3) return -1;
-
- pcic->pciitp = 0xff; /* clear interrupts */
-
- pcic->pcisa = paddr;
- pcic->pcidma = 0x700 | len;
- pcic->pcidmaa = addr;
-
- while (pcic->pciitp == 0)
- ;
-
- if (pcic->pciitp & 0x7F) retval = -1;
-
- pcic->pciitp = 0xff; /* clear interrupts */
-
- if (pcic->pcisc & 0x20000000) { /* Master Abort */
- pcic->pcisc |= 0x20000000;
- retval = -1;
- }
-
- return retval;
-}
-
-/* Transfer len number of words from addr to paddr */
-int dma_to_pci(unsigned int addr, unsigned int paddr, unsigned int len) {
-
- int tmp_len;
-
- /* Align to 1k boundary */
- tmp_len = ((addr + 1024) & 0xfffffc00) - addr;
-
- tmp_len = (tmp_len/4 < len) ? tmp_len : (len*4);
-
- if (dma_to_pci_1k(addr, paddr, tmp_len/4) < 0)
- return -1;
-
- addr += tmp_len;
- paddr += tmp_len;
- len -= tmp_len/4;
-
- /* Transfer all 1k blocks */
- while (len >= 128) {
-
- if (dma_to_pci_1k(addr, paddr, 128) < 0)
- return -1;
-
- addr += 512;
- paddr += 512;
- len -= 128;
-
- }
-
- /* Transfer last words */
- if (len) return dma_to_pci_1k(addr, paddr, len);
-
- return 0;
-}
-
-/* Transfer len number of words from paddr to addr */
-int dma_from_pci(unsigned int addr, unsigned int paddr, unsigned int len) {
-
- int tmp_len;
-
- /* Align to 1k boundary */
- tmp_len = ((addr + 1024) & 0xfffffc00) - addr;
-
- tmp_len = (tmp_len/4 < len) ? tmp_len : (len*4);
-
- if (dma_from_pci_1k(addr, paddr, tmp_len/4) < 0)
- return -1;
-
- addr += tmp_len;
- paddr += tmp_len;
- len -= tmp_len/4;
-
- /* Transfer all 1k blocks */
- while (len >= 128) {
-
- if (dma_from_pci_1k(addr, paddr, 128) < 0)
- return -1;
- addr += 512;
- paddr += 512;
- len -= 128;
-
- }
-
- /* Transfer last words */
- if (len) return dma_from_pci_1k(addr, paddr, len);
-
- return 0;
-}
-
-void pci_mem_enable(unsigned char bus, unsigned char slot,
- unsigned char function) {
- uint32_t data;
-
- pci_read_config_dword(0, slot, function, PCI_COMMAND, &data);
- pci_write_config_dword(0, slot, function, PCI_COMMAND,
- data | PCI_COMMAND_MEMORY);
-
-}
-
-void pci_master_enable(unsigned char bus, unsigned char slot,
- unsigned char function) {
- uint32_t data;
-
- pci_read_config_dword(0, slot, function, PCI_COMMAND, &data);
- pci_write_config_dword(0, slot, function, PCI_COMMAND,
- data | PCI_COMMAND_MASTER);
-
-}
-
-static inline void swap_res(struct pci_res **p1, struct pci_res **p2) {
-
- struct pci_res *tmp = *p1;
- *p1 = *p2;
- *p2 = tmp;
-
-}
-
-/* pci_allocate_resources
- *
- * This function scans the bus and assigns PCI addresses to all devices. It
- * handles both single function and multi function devices. All allocated
- * devices are enabled and latency timers are set to 40.
- *
- * NOTE that it only allocates PCI memory space devices. IO spaces are
- * not enabled. Also, it does not handle pci-pci bridges. They are left
- * disabled.
- *
- */
-static void pci_allocate_resources(void) {
-
- uint32_t slot, numfuncs, func, id, pos, size, tmp;
- unsigned int i, swapped, addr, dev, fn;
- unsigned char header;
- struct pci_res **res;
-
- res = (struct pci_res **) malloc(sizeof(struct pci_res *)*32*8*6);
-
- for (i = 0; i < 32*8*6; i++) {
- res[i] = (struct pci_res *) malloc(sizeof(struct pci_res));
- res[i]->size = 0;
- res[i]->devfn = i;
- }
-
- for(slot = 0; slot< PCI_MAX_DEVICES; slot++) {
-
- pci_read_config_dword(0, slot, 0, PCI_VENDOR_ID, &id);
-
- if(id == PCI_INVALID_VENDORDEVICEID || id == 0) {
- /*
- * This slot is empty
- */
- continue;
- }
-
- pci_read_config_byte(0, slot, 0, PCI_HEADER_TYPE, &header);
-
- if(header & PCI_HEADER_TYPE_MULTI_FUNCTION) {
- numfuncs = PCI_MAX_FUNCTIONS;
- }
- else {
- numfuncs = 1;
- }
-
- for(func = 0; func < numfuncs; func++) {
-
- pci_read_config_dword(0, slot, func, PCI_VENDOR_ID, &id);
- if(id == PCI_INVALID_VENDORDEVICEID || id == 0) {
- continue;
- }
-
- pci_read_config_dword(0, slot, func, PCI_CLASS_REVISION, &tmp);
- tmp >>= 16;
- if (tmp == PCI_CLASS_BRIDGE_PCI) {
- continue;
- }
-
- for (pos = 0; pos < 6; pos++) {
- pci_write_config_dword(0, slot, func,
- PCI_BASE_ADDRESS_0 + (pos<<2), 0xffffffff);
- pci_read_config_dword(0, slot, func,
- PCI_BASE_ADDRESS_0 + (pos<<2), &size);
-
- if (size == 0 || size == 0xffffffff || (size & 0xff) != 0) {
- pci_write_config_dword(0, slot, func,
- PCI_BASE_ADDRESS_0 + (pos<<2), 0);
- continue;
- }
-
- else {
- res[slot*8*6+func*6+pos]->size = ~size+1;
- res[slot*8*6+func*6+pos]->devfn = slot*8 + func;
- res[slot*8*6+func*6+pos]->bar = pos;
-
- DBG("Slot: %d, function: %d, bar%d size: %x\n",
- slot, func, pos, ~size+1);
- }
- }
- }
- }
-
-
- /* Sort the resources in descending order */
-
- swapped = 1;
- while (swapped == 1) {
- swapped = 0;
- for (i = 0; i < 32*8*6-1; i++) {
- if (res[i]->size < res[i+1]->size) {
- swap_res(&res[i], &res[i+1]);
- swapped = 1;
- }
- }
- i++;
- }
-
- /* Assign the BARs */
-
- addr = PCI_MEM_START;
- for (i = 0; i < 32*8*6; i++) {
-
- if (res[i]->size == 0) {
- goto done;
- }
- if ( (addr + res[i]->size) > PCI_MEM_END) {
- printk("Out of PCI memory space, all devices not configured.\n");
- goto done;
- }
-
- dev = res[i]->devfn >> 3;
- fn = res[i]->devfn & 7;
-
- DBG("Assigning PCI addr %x to device %d, function %d, bar %d\n",
- addr, dev, fn, res[i]->bar);
- pci_write_config_dword(0, dev, fn,
- PCI_BASE_ADDRESS_0+res[i]->bar*4, addr);
- addr += res[i]->size;
-
- /* Set latency timer to 64 */
- pci_read_config_dword(0, dev, fn, 0xC, &tmp);
- pci_write_config_dword(0, dev, fn, 0xC, tmp|0x4000);
-
- pci_mem_enable(0, dev, fn);
-
- }
-
-
-
-done:
-
-#ifdef PCI_INFO
- printk("\nPCI devices found and configured:\n");
- for (slot = 0; slot < PCI_MAX_DEVICES; slot++) {
-
- pci_read_config_byte(0, slot, 0, PCI_HEADER_TYPE, &header);
-
- if(header & PCI_HEADER_TYPE_MULTI_FUNCTION) {
- numfuncs = PCI_MAX_FUNCTIONS;
- }
- else {
- numfuncs = 1;
- }
-
- for (func = 0; func < numfuncs; func++) {
-
- pci_read_config_dword(0, slot, func, PCI_COMMAND, &tmp);
-
- if (tmp & PCI_COMMAND_MEMORY) {
-
- pci_read_config_dword(0, slot, func, PCI_VENDOR_ID, &id);
-
- if (id == PCI_INVALID_VENDORDEVICEID || id == 0) continue;
-
- printk("\nSlot %d function: %d\nVendor id: 0x%x, "
- "device id: 0x%x\n", slot, func, id & 0xffff, id>>16);
-
- for (pos = 0; pos < 6; pos++) {
- pci_read_config_dword(0, slot, func,
- PCI_BASE_ADDRESS_0 + pos*4, &tmp);
-
- if (tmp != 0 && tmp != 0xffffffff && (tmp & 0xff) == 0) {
-
- printk("\tBAR %d: %x\n", pos, tmp);
- }
-
- }
- printk("\n");
-
- }
-
- }
- }
- printk("\n");
-#endif
-
- for (i = 0; i < 1536; i++) {
- free(res[i]);
- }
- free(res);
-}
-
-
-
-
-
-
-
-/*
- * This routine determines the maximum bus number in the system
- */
-int init_pci(void)
-{
- unsigned char ucSlotNumber, ucFnNumber, ucNumFuncs;
- unsigned char ucHeader;
- unsigned char ucMaxSubordinate;
- uint32_t ulClass, ulDeviceID;
-
- init_at697_pci();
- pci_allocate_resources();
-
-/*
- * Scan PCI bus 0 looking for PCI-PCI bridges
- */
- for(ucSlotNumber=0;ucSlotNumber<PCI_MAX_DEVICES;ucSlotNumber++) {
- (void)pci_read_config_dword(0,
- ucSlotNumber,
- 0,
- PCI_VENDOR_ID,
- &ulDeviceID);
- if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
-/*
- * This slot is empty
- */
- continue;
- }
- (void)pci_read_config_byte(0,
- ucSlotNumber,
- 0,
- PCI_HEADER_TYPE,
- &ucHeader);
- if(ucHeader&PCI_HEADER_TYPE_MULTI_FUNCTION) {
- ucNumFuncs=PCI_MAX_FUNCTIONS;
- }
- else {
- ucNumFuncs=1;
- }
- for(ucFnNumber=0;ucFnNumber<ucNumFuncs;ucFnNumber++) {
- (void)pci_read_config_dword(0,
- ucSlotNumber,
- ucFnNumber,
- PCI_VENDOR_ID,
- &ulDeviceID);
- if(ulDeviceID==PCI_INVALID_VENDORDEVICEID) {
-/*
- * This slot/function is empty
- */
- continue;
- }
-
-/*
- * This slot/function has a device fitted.
- */
- (void)pci_read_config_dword(0,
- ucSlotNumber,
- ucFnNumber,
- PCI_CLASS_REVISION,
- &ulClass);
- ulClass >>= 16;
- if (ulClass == PCI_CLASS_BRIDGE_PCI) {
-/*
- * We have found a PCI-PCI bridge
- */
- (void)pci_read_config_byte(0,
- ucSlotNumber,
- ucFnNumber,
- PCI_SUBORDINATE_BUS,
- &ucMaxSubordinate);
- if(ucMaxSubordinate>ucMaxPCIBus) {
- ucMaxPCIBus=ucMaxSubordinate;
- }
- }
- }
- }
- return 0;
-}
-
-/*
- * Return the number of PCI busses in the system
- */
-unsigned char BusCountPCI(void)
-{
- return(ucMaxPCIBus+1);
-}