diff options
Diffstat (limited to 'c/src/lib/libbsp/sparc/shared/pci/gr_701.c')
-rw-r--r-- | c/src/lib/libbsp/sparc/shared/pci/gr_701.c | 623 |
1 files changed, 0 insertions, 623 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_701.c b/c/src/lib/libbsp/sparc/shared/pci/gr_701.c deleted file mode 100644 index a6c9ebcd5c..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_701.c +++ /dev/null @@ -1,623 +0,0 @@ -/* GR-701 PCI Target driver. - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * Configures the GR-701 interface PCI board. - * This driver provides a AMBA PnP bus by using the general part - * of the AMBA PnP bus driver (ambapp_bus.c). - * - * Driver resources for the AMBA PnP bus provided can be set using - * gr701_set_resources(). - * - * The license and distribution terms for this file may be - * found in found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <bsp.h> -#include <rtems/bspIo.h> -#include <rtems/score/isrlock.h> /* spin-lock */ -#include <pci.h> -#include <pci/access.h> - -#include <ambapp.h> - -#include <ambapp.h> -#include <drvmgr/drvmgr.h> -#include <drvmgr/ambapp_bus.h> -#include <drvmgr/pci_bus.h> -#include <drvmgr/bspcommon.h> -#include <bsp/genirq.h> - -#include <bsp/gr_701.h> - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -/* Offset from 0x80000000 (dual bus version) */ -#define AHB1_BASE_ADDR 0x80000000 -#define AHB1_IOAREA_BASE_ADDR 0x80100000 - -/* #define DEBUG 1 */ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -int gr701_init1(struct drvmgr_dev *dev); -int gr701_init2(struct drvmgr_dev *dev); -void gr701_interrupt(void *arg); - -#define READ_REG(address) (*(volatile unsigned int *)address) - -/* PCI bride reg layout on AMBA side */ -struct amba_bridge_regs { - volatile unsigned int bar0; - volatile unsigned int bar1; - volatile unsigned int bar2; - volatile unsigned int bar3; - volatile unsigned int bar4;/* 0x10 */ - - volatile unsigned int unused[4*3-1]; - - volatile unsigned int ambabars[1]; /* 0x40 */ -}; - -/* PCI bride reg layout on PCI side */ -struct pci_bridge_regs { - volatile unsigned int bar0; - volatile unsigned int bar1; - volatile unsigned int bar2; - volatile unsigned int bar3; - volatile unsigned int bar4; /* 0x10 */ - - volatile unsigned int ilevel; - volatile unsigned int ipend; - volatile unsigned int iforce; - volatile unsigned int istatus; - volatile unsigned int iclear; - volatile unsigned int imask; -}; - -/* Private data structure for driver */ -struct gr701_priv { - /* Driver management */ - struct drvmgr_dev *dev; - char prefix[16]; - SPIN_DECLARE(devlock); - - struct pci_bridge_regs *pcib; - struct amba_bridge_regs *ambab; - - /* PCI */ - pci_dev_t pcidev; - struct pci_dev_info *devinfo; - - /* IRQ */ - genirq_t genirq; - int interrupt_cnt; - - /* GR-701 Address translation */ - struct drvmgr_map_entry bus_maps_up[2]; - struct drvmgr_map_entry bus_maps_down[2]; - - /* AMBA Plug&Play information on GR-701 */ - struct ambapp_bus abus; - struct ambapp_mmap amba_maps[3]; - struct ambapp_config config; -}; - -int ambapp_gr701_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg); -int ambapp_gr701_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr isr, - void *arg); -int ambapp_gr701_int_unmask( - struct drvmgr_dev *dev, - int irq); -int ambapp_gr701_int_mask( - struct drvmgr_dev *dev, - int irq); -int ambapp_gr701_int_clear( - struct drvmgr_dev *dev, - int irq); -int ambapp_gr701_get_params( - struct drvmgr_dev *dev, - struct drvmgr_bus_params *params); - -struct ambapp_ops ambapp_gr701_ops = { - .int_register = ambapp_gr701_int_register, - .int_unregister = ambapp_gr701_int_unregister, - .int_unmask = ambapp_gr701_int_unmask, - .int_mask = ambapp_gr701_int_mask, - .int_clear = ambapp_gr701_int_clear, - .get_params = ambapp_gr701_get_params -}; - -struct drvmgr_drv_ops gr701_ops = -{ - .init = {gr701_init1, gr701_init2, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct pci_dev_id_match gr701_ids[] = -{ - PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_701), - PCIID_END_TABLE /* Mark end of table */ -}; - -struct pci_drv_info gr701_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_PCI_GAISLER_GR701_ID, /* Driver ID */ - "GR-701_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_PCI, /* Bus Type */ - &gr701_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &gr701_ids[0] -}; - -/* Driver resources configuration for the AMBA bus on the GR-701 board. - * It is declared weak so that the user may override it from the project file, - * if the default settings are not enough. - * - * The configuration consists of an array of configuration pointers, each - * pointer determine the configuration of one GR-701 board. Pointer - * zero is for board0, pointer 1 for board1 and so on. - * - * The array must end with a NULL pointer. - */ -struct drvmgr_bus_res *gr701_resources[] __attribute__((weak)) = -{ - NULL -}; - -void gr701_register_drv(void) -{ - DBG("Registering GR-701 PCI driver\n"); - drvmgr_drv_register(&gr701_info.general); -} - -void gr701_interrupt(void *arg) -{ - struct gr701_priv *priv = arg; - unsigned int status; - int irq = 0; - SPIN_ISR_IRQFLAGS(irqflags); - - SPIN_LOCK(&priv->devlock, irqflags); - while ( (status=priv->pcib->istatus) != 0 ) { - priv->interrupt_cnt++; /* An interrupt was generated */ - irq = status; - genirq_doirq(priv->genirq, irq); - /* ACK interrupt */ - priv->pcib->istatus = 0; - } - SPIN_UNLOCK(&priv->devlock, irqflags); - - /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */ - if ( irq ) - drvmgr_interrupt_clear(priv->dev, 0); -} - -static int gr701_hw_init(struct gr701_priv *priv) -{ - uint32_t com1; - struct pci_bridge_regs *pcib; - struct amba_bridge_regs *ambab; - int mst; - unsigned int pci_freq_hz; - pci_dev_t pcidev = priv->pcidev; - struct pci_dev_info *devinfo = priv->devinfo; - - /* Set up PCI ==> AMBA */ - priv->pcib = pcib = (void *)devinfo->resources[0].address; - pcib->bar0 = 0xfc000000; - - /* Set up GR701 AMBA Masters connection to PCI */ - priv->ambab = ambab = (struct amba_bridge_regs *)( - devinfo->resources[1].address + 0x400); - - /* Init all msters, max 16 */ - for (mst=0; mst<16; mst++) { - ambab->ambabars[mst] = 0x40000000; - if (READ_REG(&ambab->ambabars[mst]) != 0x40000000) - break; - } - - /* Setup Address translation for AMBA bus, assume that PCI BAR - * are mapped 1:1 to CPU. - */ - - priv->amba_maps[0].size = 0x04000000; - priv->amba_maps[0].local_adr = devinfo->resources[1].address; - priv->amba_maps[0].remote_adr = 0xfc000000; - - /* Mark end of table */ - priv->amba_maps[1].size=0; - priv->amba_maps[1].local_adr = 0; - priv->amba_maps[1].remote_adr = 0; - - /* Setup DOWN-streams address translation */ - priv->bus_maps_down[0].name = "PCI BAR1 -> AMBA"; - priv->bus_maps_down[0].size = priv->amba_maps[0].size; - priv->bus_maps_down[0].from_adr = (void *)devinfo->resources[1].address; - priv->bus_maps_down[0].to_adr = (void *)0xfc000000; - - /* Setup UP-streams address translation */ - priv->bus_maps_up[0].name = "AMBA PCIF Window"; - priv->bus_maps_up[0].size = 0x10000000; - priv->bus_maps_up[0].from_adr = (void *)0xe0000000; - priv->bus_maps_up[0].to_adr = (void *)0x40000000; - - /* Mark end of translation tables */ - priv->bus_maps_down[1].size = 0; - priv->bus_maps_up[1].size = 0; - - /* Enable I/O and Mem accesses */ - pci_cfg_r32(pcidev, PCIR_COMMAND, &com1); - com1 |= PCIM_CMD_PORTEN | PCIM_CMD_MEMEN; - pci_cfg_w32(pcidev, PCIR_COMMAND, com1); - - /* Start AMBA PnP scan at first AHB bus */ - ambapp_scan(&priv->abus, devinfo->resources[1].address + 0x3f00000, - NULL, &priv->amba_maps[0]); - - /* Frequency is the same as the PCI bus frequency */ - drvmgr_freq_get(priv->dev, 0, &pci_freq_hz); - - /* Initialize Frequency of AMBA bus */ - ambapp_freq_init(&priv->abus, NULL, pci_freq_hz); - - /* Init IRQ controller (avoid IRQ generation) */ - pcib->imask = 0x0000; - pcib->ipend = 0; - pcib->iclear = 0xffff; - pcib->iforce = 0; - pcib->ilevel = 0x0; - - /* Successfully registered the GR-701 board */ - return 0; -} - -static void gr701_hw_init2(struct gr701_priv *priv) -{ - /* Enable PCI Master (for DMA) */ - pci_master_enable(priv->pcidev); -} - -/* Called when a PCI target is found with the PCI device and vendor ID - * given in gr701_ids[]. - */ -int gr701_init1(struct drvmgr_dev *dev) -{ - struct gr701_priv *priv; - struct pci_dev_info *devinfo; - uint32_t bar0, bar1, bar0_size, bar1_size; - int resources_cnt; - - priv = malloc(sizeof(struct gr701_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - - memset(priv, 0, sizeof(*priv)); - dev->priv = priv; - priv->dev = dev; - - /* Determine number of configurations */ - resources_cnt = get_resarray_count(gr701_resources); - - /* Generate Device prefix */ - strcpy(priv->prefix, "/dev/gr701_0"); - priv->prefix[11] += dev->minor_drv; - mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO); - priv->prefix[12] = '/'; - priv->prefix[13] = '\0'; - - priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo; - priv->pcidev = devinfo->pcidev; - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - bar1 = devinfo->resources[1].address; - bar1_size = devinfo->resources[1].size; - printf("\n\n--- GR-701[%d] ---\n", dev->minor_drv); - printf(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n", - PCI_DEV_EXPAND(priv->pcidev)); - printf(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n\n\n", - devinfo->id.vendor, devinfo->id.device); - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" PCI BAR[1]: 0x%lx - 0x%lx\n", bar1, bar1 + bar1_size - 1); - printf(" IRQ: %d\n\n\n", devinfo->irq); - - /* all neccessary space assigned to GR-701 target? */ - if ((bar0_size == 0) || (bar1_size == 0)) - return DRVMGR_ENORES; - - /* Initialize spin-lock for this PCI perihperal device. This is to - * protect the Interrupt Controller Registers. The genirq layer is - * protecting its own internals and ISR dispatching. - */ - SPIN_INIT(&priv->devlock, priv->prefix); - - priv->genirq = genirq_init(16); - if ( priv->genirq == NULL ) { - free(priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - if ( gr701_hw_init(priv) ) { - genirq_destroy(priv->genirq); - free(priv); - dev->priv = NULL; - printf(" Failed to initialize GR-701 HW\n"); - return DRVMGR_FAIL; - } - - /* Init amba bus */ - priv->config.abus = &priv->abus; - priv->config.ops = &ambapp_gr701_ops; - priv->config.maps_up = &priv->bus_maps_up[0]; - priv->config.maps_down = &priv->bus_maps_down[0]; - if ( priv->dev->minor_drv < resources_cnt ) { - priv->config.resources = gr701_resources[priv->dev->minor_drv]; - } else { - priv->config.resources = NULL; - } - - /* Create and register AMBA PnP bus. */ - return ambapp_bus_register(dev, &priv->config); -} - -/* Called when a PCI target is found with the PCI device and vendor ID - * given in gr701_ids[]. - */ -int gr701_init2(struct drvmgr_dev *dev) -{ - struct gr701_priv *priv = dev->priv; - - /* Clear any old interrupt requests */ - drvmgr_interrupt_clear(dev, 0); - - /* Enable System IRQ so that GR-701 PCI target interrupt goes through. - * - * It is important to enable it in stage init2. If interrupts were - * enabled in init1 this might hang the system when more than one PCI - * board is connected, this is because PCI interrupts might be shared - * and PCI target 2 have not initialized and might therefore drive - * interrupt already when entering init1(). - */ - drvmgr_interrupt_register(dev, 0, "gr701", gr701_interrupt, priv); - - gr701_hw_init2(priv); - - return DRVMGR_OK; -} - -int ambapp_gr701_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg) -{ - struct gr701_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *h; - - h = genirq_alloc_handler(handler, arg); - if ( h == NULL ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_register(priv->genirq, irq, h); - if ( status == 0 ) { - /* Clear IRQ for first registered handler */ - priv->pcib->iclear = (1<<irq); - } else if ( status == 1 ) - status = 0; - - if (status != 0) { - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - genirq_free_handler(h); - return DRVMGR_FAIL; - } - - status = genirq_enable(priv->genirq, irq, handler, arg); - if ( status == 0 ) { - /* Enable IRQ for first enabled handler only */ - priv->pcib->imask |= (1<<irq); /* unmask interrupt source */ - } else if ( status == 1 ) - status = DRVMGR_OK; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - return status; -} - -int ambapp_gr701_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr isr, - void *arg) -{ - struct gr701_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *handler; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_disable(priv->genirq, irq, isr, arg); - if ( status == 0 ) { - /* Disable IRQ only when no enabled handler exists */ - priv->pcib->imask &= ~(1<<irq); /* mask interrupt source */ - } - - handler = genirq_unregister(priv->genirq, irq, isr, arg); - if ( handler == NULL ) - status = DRVMGR_FAIL; - else - status = DRVMGR_OK; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - if (handler) - genirq_free_handler(handler); - - return status; -} - -int ambapp_gr701_int_unmask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr701_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("GR-701 IRQ %d: enable\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Enable IRQ */ - priv->pcib->imask |= (1<<irq); /* unmask interrupt source */ - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_gr701_int_mask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr701_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("GR-701 IRQ %d: disable\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Disable IRQ */ - priv->pcib->imask &= ~(1<<irq); /* mask interrupt source */ - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_gr701_int_clear( - struct drvmgr_dev *dev, - int irq) -{ - struct gr701_priv *priv = dev->parent->dev->priv; - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_FAIL; - - priv->pcib->iclear = (1<<irq); - - return DRVMGR_OK; -} - -int ambapp_gr701_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params) -{ - struct gr701_priv *priv = dev->parent->dev->priv; - - /* Device name prefix pointer, skip /dev */ - params->dev_prefix = &priv->prefix[5]; - - return 0; -} - -void gr701_print_dev(struct drvmgr_dev *dev, int options) -{ - struct gr701_priv *priv = dev->priv; - struct pci_dev_info *devinfo = priv->devinfo; - unsigned int freq_hz; - uint32_t bar0, bar1, bar0_size, bar1_size; - - /* Print */ - printf("--- GR-701 [bus 0x%x, dev 0x%x, fun 0x%x] ---\n", - PCI_DEV_EXPAND(priv->pcidev)); - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - bar1 = devinfo->resources[1].address; - bar1_size = devinfo->resources[1].size; - - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" PCI BAR[1]: 0x%lx - 0x%lx\n", bar1, bar1 + bar1_size - 1); - printf(" IRQ: %d\n", devinfo->irq); - - /* Frequency is the same as the PCI bus frequency */ - drvmgr_freq_get(dev, 0, &freq_hz); - - printf(" FREQ: %u Hz\n", freq_hz); - printf(" IMASK: 0x%08x\n", priv->pcib->imask); - printf(" IPEND: 0x%08x\n", priv->pcib->ipend); - - /* Print amba config */ - if ( options & GR701_OPTIONS_AMBA ) { - ambapp_print(&priv->abus, 10); - } - -#if 0 - /* Print IRQ handlers and their arguments */ - if ( options & GR701_OPTIONS_IRQ ) { - int i; - for(i=0; i<16; i++) { - printf(" IRQ[%02d]: 0x%x, arg: 0x%x\n", - i, (unsigned int)priv->isrs[i].handler, (unsigned int)priv->isrs[i].arg); - } - } -#endif -} - -void gr701_print(int options) -{ - struct pci_drv_info *drv = &gr701_info; - struct drvmgr_dev *dev; - - dev = drv->general.dev; - while(dev) { - gr701_print_dev(dev, options); - dev = dev->next_in_drv; - } -} |