summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/leon3
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/leon3
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/leon3')
-rw-r--r--c/src/lib/libbsp/sparc/leon3/Makefile.am9
-rw-r--r--c/src/lib/libbsp/sparc/leon3/pci/pci.c613
-rw-r--r--c/src/lib/libbsp/sparc/leon3/preinstall.am6
3 files changed, 10 insertions, 618 deletions
diff --git a/c/src/lib/libbsp/sparc/leon3/Makefile.am b/c/src/lib/libbsp/sparc/leon3/Makefile.am
index f263ab607a..a451208904 100644
--- a/c/src/lib/libbsp/sparc/leon3/Makefile.am
+++ b/c/src/lib/libbsp/sparc/leon3/Makefile.am
@@ -100,9 +100,14 @@ libbsp_a_SOURCES += \
../../shared/src/irq-legacy.c \
../../shared/src/irq-server.c \
../../shared/src/irq-shell.c
+
# PCI
-include_HEADERS += ../../sparc/shared/include/pci.h
-libbsp_a_SOURCES += pci/pci.c ../../sparc/shared/pci/pcifinddevice.c
+include_HEADERS += ../../sparc/shared/include/grpci2.h
+libbsp_a_SOURCES += ../../sparc/shared/pci/grpci.c
+libbsp_a_SOURCES += ../../sparc/shared/pci/grpci2.c
+libbsp_a_SOURCES += ../../sparc/shared/pci/pcif.c
+libbsp_a_SOURCES += ../../sparc/shared/pci/pci_memreg_sparc_le.c
+libbsp_a_SOURCES += ../../sparc/shared/pci/pci_memreg_sparc_be.c
# B1553BRM
include_HEADERS += ../../sparc/shared/include/b1553brm.h \
diff --git a/c/src/lib/libbsp/sparc/leon3/pci/pci.c b/c/src/lib/libbsp/sparc/leon3/pci/pci.c
deleted file mode 100644
index 5e95cbc2a0..0000000000
--- a/c/src/lib/libbsp/sparc/leon3/pci/pci.c
+++ /dev/null
@@ -1,613 +0,0 @@
-/*
- * 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 GRPCI
- * Copyright (C) 2006 Gaisler Research
- *
- */
-
-#include <pci.h>
-#include <stdlib.h>
-#include <rtems/bspIo.h>
-
-#define PCI_ADDR 0x80000400
-#define DMAPCI_ADDR 0x80000500
-#define PCI_CONF 0xfff50000
-#define PCI_MEM_START 0xe0000000
-#define PCI_MEM_END 0xf0000000
-#define PCI_MEM_SIZE (PCI_MEM_START - PCI_MEM_END)
-
-/* If uncommented byte twisting is enabled */
-/*#define BT_ENABLED 1*/
-
-/* 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 {
- volatile unsigned int cfg_stat;
- volatile unsigned int bar0;
- volatile unsigned int page0;
- volatile unsigned int bar1;
- volatile unsigned int page1;
- volatile unsigned int iomap;
- volatile unsigned int stat_cmd;
-} LEON3_GRPCI_Regs_Map;
-
-LEON3_GRPCI_Regs_Map *pcic = (LEON3_GRPCI_Regs_Map *) PCI_ADDR;
-unsigned int *pcidma = (unsigned int *)DMAPCI_ADDR;
-
-struct pci_res {
- unsigned int size;
- unsigned char bar;
- unsigned char devfn;
-};
-
-static inline unsigned int flip_dword (unsigned int l)
-{
- return ((l&0xff)<<24) | (((l>>8)&0xff)<<16) |
- (((l>>16)&0xff)<<8)| ((l>>24)&0xff);
-}
-
-
-/* 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 unsigned int *pci_conf;
-
- if (offset & 3) return PCIBIOS_BAD_REGISTER_NUMBER;
-
- if (slot > 21) {
- *val = 0xffffffff;
- return PCIBIOS_SUCCESSFUL;
- }
-
- pci_conf = (volatile unsigned int *) (PCI_CONF +
- ((slot<<11) | (function<<8) | offset));
-
-#ifdef BT_ENABLED
- *val = flip_dword(*pci_conf);
-#else
- *val = *pci_conf;
-#endif
-
- if (pcic->cfg_stat & 0x100) {
- *val = 0xffffffff;
- }
-
- 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) {
-
- volatile unsigned int *pci_conf;
- unsigned int value;
-
- if (offset & 3 || bus != 0) return PCIBIOS_BAD_REGISTER_NUMBER;
-
-
- pci_conf = (volatile unsigned int *) (PCI_CONF +
- ((slot<<11) | (function<<8) | (offset & ~3)));
-
-#ifdef BT_ENABLED
- value = flip_dword(val);
-#else
- value = val;
-#endif
-
- *pci_conf = value;
-
- 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), value);
-
- 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 int init_grpci(void) {
-
- volatile unsigned int *page0 = (unsigned volatile int *) PCI_MEM_START;
- uint32_t data;
-#ifndef BT_ENABLED
- uint32_t addr;
-#endif
-
-#ifndef BT_ENABLED
- pci_write_config_dword(0,0,0,0x10, 0xffffffff);
- pci_read_config_dword(0,0,0,0x10, &addr);
- /* Setup bar0 to nonzero value (grpci considers BAR==0 as invalid) */
- pci_write_config_dword(0,0,0,0x10, flip_dword(0x10000000));
- /* page0 is accessed through upper half of bar0 */
- addr = (~flip_dword(addr)+1)>>1;
- /* Setup mmap reg so we can reach bar0 */
- pcic->cfg_stat |= 0x10000000;
- /* Disable bytetwisting ... */
- page0[addr/4] = 0;
-#endif
-
- /* set 1:1 mapping between AHB -> PCI memory */
- pcic->cfg_stat = (pcic->cfg_stat & 0x0fffffff) | PCI_MEM_START;
-
- /* and map system RAM at pci address 0x40000000 */
- pci_write_config_dword(0, 0, 0, 0x14, 0x40000000);
- pcic->page1 = 0x40000000;
-
- /* set as bus master and enable pci memory responses */
- pci_read_config_dword(0, 0, 0, 0x4, &data);
- pci_write_config_dword(0, 0, 0, 0x4, data | 0x6);
-
- return 0;
-}
-
-/* DMA functions which uses GRPCIs optional DMA controller (len in words) */
-int dma_to_pci(unsigned int ahb_addr, unsigned int pci_addr,
- unsigned int len) {
- int ret = 0;
-
- pcidma[0] = 0x82;
- pcidma[1] = ahb_addr;
- pcidma[2] = pci_addr;
- pcidma[3] = len;
- pcidma[0] = 0x83;
-
- while ( (pcidma[0] & 0x4) == 0)
- ;
-
- if (pcidma[0] & 0x8) { /* error */
- ret = -1;
- }
-
- pcidma[0] |= 0xC;
- return ret;
-
-}
-
-int dma_from_pci(unsigned int ahb_addr, unsigned int pci_addr,
- unsigned int len) {
- int ret = 0;
-
- pcidma[0] = 0x80;
- pcidma[1] = ahb_addr;
- pcidma[2] = pci_addr;
- pcidma[3] = len;
- pcidma[0] = 0x81;
-
- while ( (pcidma[0] & 0x4) == 0)
- ;
-
- if (pcidma[0] & 0x8) { /* error */
- ret = -1;
- }
-
- pcidma[0] |= 0xC;
- return ret;
-
-}
-
-
-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 (that are at
- * least 1 KB). IO spaces are not enabled. Also, it does not handle
- * pci-pci bridges. They are left disabled.
- *
-*/
-static void pci_allocate_resources(void) {
-
- unsigned int slot, numfuncs, func, pos, i, swapped, addr, dev, fn;
- uint32_t id, tmp, size;
- 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 = 1; 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 & 0x3f1) != 0){
- pci_write_config_dword(0, slot, func,
- PCI_BASE_ADDRESS_0 + (pos<<2), 0);
- continue;
-
- }else {
- size &= 0xfffffff0;
- 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 = 1; 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 & 0x3f1) == 0) {
-
- printk("\tBAR %d: %x\n", pos, tmp);
- }
-
- }
- printk("\n");
-
- }
-
- }
- }
- printk("\n");
-#endif
-
- for (i = 0; i < 1536; i++) {
- free(res[i]);
- }
- free(res);
-}
-
-
-
-int init_pci(void)
-{
- unsigned char ucSlotNumber, ucFnNumber, ucNumFuncs;
- unsigned char ucHeader;
- unsigned char ucMaxSubordinate;
- uint32_t ulClass, ulDeviceID;
-
- DBG("Initializing PCI\n");
- if ( init_grpci() ) {
- return -1;
- }
- pci_allocate_resources();
- DBG("PCI resource allocation done\n");
-/*
- * 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);
-}
diff --git a/c/src/lib/libbsp/sparc/leon3/preinstall.am b/c/src/lib/libbsp/sparc/leon3/preinstall.am
index a45fc31353..a12563a524 100644
--- a/c/src/lib/libbsp/sparc/leon3/preinstall.am
+++ b/c/src/lib/libbsp/sparc/leon3/preinstall.am
@@ -125,9 +125,9 @@ $(PROJECT_INCLUDE)/bsp/irq.h: include/bsp/irq.h $(PROJECT_INCLUDE)/bsp/$(dirstam
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq.h
-$(PROJECT_INCLUDE)/pci.h: ../../sparc/shared/include/pci.h $(PROJECT_INCLUDE)/$(dirstamp)
- $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/pci.h
-PREINSTALL_FILES += $(PROJECT_INCLUDE)/pci.h
+$(PROJECT_INCLUDE)/grpci2.h: ../../sparc/shared/include/grpci2.h $(PROJECT_INCLUDE)/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grpci2.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/grpci2.h
$(PROJECT_INCLUDE)/b1553brm.h: ../../sparc/shared/include/b1553brm.h $(PROJECT_INCLUDE)/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/b1553brm.h