From 67e472cb4242c9bd0e2f12a7ef887a335f1045ff Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 20 Apr 2018 13:45:16 +0200 Subject: bsps/leon2: Move PCI driver to bsps This patch is a part of the BSP source reorganization. Update #3285. --- c/src/lib/libbsp/sparc/leon2/Makefile.am | 2 +- c/src/lib/libbsp/sparc/leon2/pci/at697_pci.c | 656 --------------------------- 2 files changed, 1 insertion(+), 657 deletions(-) delete mode 100644 c/src/lib/libbsp/sparc/leon2/pci/at697_pci.c (limited to 'c/src/lib/libbsp/sparc') diff --git a/c/src/lib/libbsp/sparc/leon2/Makefile.am b/c/src/lib/libbsp/sparc/leon2/Makefile.am index f421bc637a..face1420bf 100644 --- a/c/src/lib/libbsp/sparc/leon2/Makefile.am +++ b/c/src/lib/libbsp/sparc/leon2/Makefile.am @@ -73,7 +73,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/grpci.c librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/pcif.c librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/pci_memreg_sparc_le.c librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/pci_memreg_sparc_be.c -librtemsbsp_a_SOURCES += pci/at697_pci.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/pci/at697_pci.c # PCI target devices librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_701.c diff --git a/c/src/lib/libbsp/sparc/leon2/pci/at697_pci.c b/c/src/lib/libbsp/sparc/leon2/pci/at697_pci.c deleted file mode 100644 index 40ba93d0f7..0000000000 --- a/c/src/lib/libbsp/sparc/leon2/pci/at697_pci.c +++ /dev/null @@ -1,656 +0,0 @@ -/* LEON2 AT697 PCI Host Driver. - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * Configures the AT697 PCI core and initialize, - * - the PCI Library (pci.c) - * - the general part of the PCI Bus driver (pci_bus.c) - * - * System interrupt assigned to PCI interrupt (INTA#..INTD#) is by - * default taken from Plug and Play, but may be overridden by the - * driver resources INTA#..INTD#. - * - * 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. - */ - -/* Configurable parameters - * ======================= - * INT[A..D]# Select system IRQ (can be tranlated into I/O interrupt) - * INT[A..D]#_PIO Select PIO used to generate I/O interrupt - * - * Notes - * ===== - * IRQ must not be enabled before all PCI boards have been enabled, the - * IRQ is therefore enabled first in init2. The init2() for this driver - * is assumed to be executed earlier that all boards and their devices - * driver's init2() function. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -/* Configuration options */ - -#define SYSTEM_MAINMEM_START 0x40000000 -#define SYSTEM_MAINMEM_START2 0x60000000 - -/* Interrupt assignment. Set to other value than 0xff in order to - * override defaults and plug&play information - */ -#ifndef AT697_INTA_SYSIRQ - #define AT697_INTA_SYSIRQ 0xff -#endif -#ifndef AT697_INTB_SYSIRQ - #define AT697_INTB_SYSIRQ 0xff -#endif -#ifndef AT697_INTC_SYSIRQ - #define AT697_INTC_SYSIRQ 0xff -#endif -#ifndef AT697_INTD_SYSIRQ - #define AT697_INTD_SYSIRQ 0xff -#endif - -#ifndef AT697_INTA_PIO - #define AT697_INTA_PIO 0xff -#endif -#ifndef AT697_INTB_PIO - #define AT697_INTB_PIO 0xff -#endif -#ifndef AT697_INTC_PIO - #define AT697_INTC_PIO 0xff -#endif -#ifndef AT697_INTD_PIO - #define AT697_INTD_PIO 0xff -#endif - - -/* AT697 PCI */ -#define AT697_PCI_REG_ADR 0x80000100 - -/* PCI Window used */ -#define PCI_MEM_START 0xa0000000 -#define PCI_MEM_END 0xf0000000 -#define PCI_MEM_SIZE (PCI_MEM_END - PCI_MEM_START) - -/* #define DEBUG 1 */ - -#ifdef DEBUG -#define DBG(x...) printf(x) -#else -#define DBG(x...) -#endif - -struct at697pci_regs { - volatile unsigned int pciid1; /* 0x80000100 - PCI Device identification register 1 */ - volatile unsigned int pcisc; /* 0x80000104 - PCI Status & Command */ - volatile unsigned int pciid2; /* 0x80000108 - PCI Device identification register 2 */ - volatile unsigned int pcibhlc; /* 0x8000010c - BIST, Header type, Cache line size register */ - volatile unsigned int mbar1; /* 0x80000110 - Memory Base Address Register 1 */ - volatile unsigned int mbar2; /* 0x80000114 - Memory Base Address Register 2 */ - volatile unsigned int iobar3; /* 0x80000118 - IO Base Address Register 3 */ - volatile unsigned int dummy1[4]; /* 0x8000011c - 0x80000128 */ - volatile unsigned int pcisid; /* 0x8000012c - Subsystem identification register */ - volatile unsigned int dummy2; /* 0x80000130 */ - volatile unsigned int pcicp; /* 0x80000134 - PCI capabilities pointer register */ - volatile unsigned int dummy3; /* 0x80000138 */ - volatile unsigned int pcili; /* 0x8000013c - PCI latency interrupt register */ - volatile unsigned int pcirt; /* 0x80000140 - PCI retry, trdy config */ - volatile unsigned int pcicw; /* 0x80000144 - PCI configuration write register */ - volatile unsigned int pcisa; /* 0x80000148 - PCI Initiator Start Address */ - volatile unsigned int pciiw; /* 0x8000014c - PCI Initiator Write Register */ - volatile unsigned int pcidma; /* 0x80000150 - PCI DMA configuration register */ - volatile unsigned int pciis; /* 0x80000154 - PCI Initiator Status Register */ - volatile unsigned int pciic; /* 0x80000158 - PCI Initiator Configuration */ - volatile unsigned int pcitpa; /* 0x8000015c - PCI Target Page Address Register */ - volatile unsigned int pcitsc; /* 0x80000160 - PCI Target Status-Command Register */ - volatile unsigned int pciite; /* 0x80000164 - PCI Interrupt Enable Register */ - volatile unsigned int pciitp; /* 0x80000168 - PCI Interrupt Pending Register */ - volatile unsigned int pciitf; /* 0x8000016c - PCI Interrupt Force Register */ - volatile unsigned int pcid; /* 0x80000170 - PCI Data Register */ - volatile unsigned int pcibe; /* 0x80000174 - PCI Burst End Register */ - volatile unsigned int pcidmaa; /* 0x80000178 - PCI DMA Address Register */ -}; - -/* PCI Interrupt assignment. Connects an PCI interrupt pin (INTA#..INTD#) - * to a system interrupt number. - */ -unsigned char at697_pci_irq_table[4] = -{ - /* INTA# */ AT697_INTA_SYSIRQ, - /* INTB# */ AT697_INTB_SYSIRQ, - /* INTC# */ AT697_INTC_SYSIRQ, - /* INTD# */ AT697_INTD_SYSIRQ -}; - -/* PCI Interrupt PIO assignment. Selects which GPIO pin will be used to - * generate the system IRQ. - * - * PCI IRQ -> GPIO -> 4 x I/O select -> System IRQ - * ^- pio_table ^- irq_select - */ -unsigned char at697_pci_irq_pio_table[4] = -{ - /* INTA# */ AT697_INTA_PIO, - /* INTB# */ AT697_INTB_PIO, - /* INTC# */ AT697_INTC_PIO, - /* INTD# */ AT697_INTD_PIO -}; - -/* Driver private data struture */ -struct at697pci_priv { - struct drvmgr_dev *dev; - struct at697pci_regs *regs; - int minor; - - uint32_t bar1_pci_adr; - uint32_t bar2_pci_adr; - - struct drvmgr_map_entry maps_up[3]; - struct drvmgr_map_entry maps_down[2]; - struct pcibus_config config; -}; - -struct at697pci_priv *at697pcipriv = NULL; -static int at697pci_minor = 0; - -int at697pci_init1(struct drvmgr_dev *dev); -int at697pci_init2(struct drvmgr_dev *dev); - -/* AT697 PCI DRIVER */ - -struct drvmgr_drv_ops at697pci_ops = -{ - .init = {at697pci_init1, at697pci_init2, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct leon2_amba_dev_id at697pci_ids[] = -{ - {LEON2_AMBA_AT697PCI_ID}, - {0} /* Mark end of table */ -}; - -struct leon2_amba_drv_info at697pci_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_LEON2_AMBA_AT697PCI, /* Driver ID */ - "AT697PCI_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_LEON2_AMBA, /* Bus Type */ - &at697pci_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - sizeof(struct at697pci_priv), /* let drvmgr alloc private */ - }, - &at697pci_ids[0] -}; - -void at697pci_register_drv(void) -{ - DBG("Registering AT697 PCI driver\n"); - drvmgr_drv_register(&at697pci_info.general); -} - -/* The configuration access functions uses the DMA functionality of the - * AT697 pci controller to be able access all slots - */ - -static int at697pci_cfg_r32(pci_dev_t dev, int offset, uint32_t *val) -{ - struct at697pci_regs *regs; - volatile unsigned int data = 0; - unsigned int address; - int bus = PCI_DEV_BUS(dev); - int slot = PCI_DEV_SLOT(dev); - int func = PCI_DEV_FUNC(dev); - int retval; - - if (slot > 15 || (offset & ~0xfc)) { - *val = 0xffffffff; - return PCISTS_EINVAL; - } - - regs = at697pcipriv->regs; - - regs->pciitp = 0xff; /* clear interrupts */ - - if ( bus == 0 ) { - /* PCI Access - TYPE 0 */ - address = (1<<(16+slot)) | (func << 8) | offset; - } else { - /* PCI access - TYPE 1 */ - address = ((bus & 0xff) << 16) | ((slot & 0x1f) << 11) | - (func << 8) | offset | 1; - } - regs->pcisa = address; - regs->pcidma = 0xa01; - regs->pcidmaa = (unsigned int) &data; - - while (regs->pciitp == 0) - ; - - regs->pciitp = 0xff; /* clear interrupts */ - - if (regs->pcisc & 0x20000000) { /* Master Abort */ - regs->pcisc |= 0x20000000; - *val = 0xffffffff; - retval = PCISTS_MSTABRT; - } else { - *val = data; - retval = PCISTS_OK; - } - - DBG("pci_read - bus: %d, dev: %d, fn: %d, off: %d => addr: %x, val: %x\n", - bus, slot, func, offset, address, *val); - - return retval; -} - -static int at697pci_cfg_r16(pci_dev_t dev, int ofs, uint16_t *val) -{ - uint32_t v; - int retval; - - if (ofs & 1) - return PCISTS_EINVAL; - - retval = at697pci_cfg_r32(dev, ofs & ~0x3, &v); - *val = 0xffff & (v >> (8*(ofs & 0x3))); - - return retval; -} - -static int at697pci_cfg_r8(pci_dev_t dev, int ofs, uint8_t *val) -{ - uint32_t v; - int retval; - - retval = at697pci_cfg_r32(dev, ofs & ~0x3, &v); - - *val = 0xff & (v >> (8*(ofs & 3))); - - return retval; -} - -static int at697pci_cfg_w32(pci_dev_t dev, int offset, uint32_t val) -{ - struct at697pci_regs *regs; - volatile unsigned int tmp_val = val; - unsigned int address; - int bus = PCI_DEV_BUS(dev); - int slot = PCI_DEV_SLOT(dev); - int func = PCI_DEV_FUNC(dev); - int retval; - - if (slot > 15 || (offset & ~0xfc)) - return PCISTS_EINVAL; - - regs = at697pcipriv->regs; - - regs->pciitp = 0xff; /* clear interrupts */ - - if ( bus == 0 ) { - /* PCI Access - TYPE 0 */ - address = (1<<(16+slot)) | (func << 8) | offset; - } else { - /* PCI access - TYPE 1 */ - address = ((bus & 0xff) << 16) | ((slot & 0x1f) << 11) | - (func << 8) | offset | 1; - } - regs->pcisa = address; - regs->pcidma = 0xb01; - regs->pcidmaa = (unsigned int) &tmp_val; - - while (regs->pciitp == 0) - ; - - if (regs->pcisc & 0x20000000) { /* Master Abort */ - regs->pcisc |= 0x20000000; - retval = PCISTS_MSTABRT; - } else - retval = PCISTS_OK; - - regs->pciitp = 0xff; /* clear interrupts */ - - DBG("pci_write - bus: %d, dev: %d, fn: %d, off: %d => addr: %x, val: %x\n", - bus, slot, func, offset, address, val); - - return retval; -} - -static int at697pci_cfg_w16(pci_dev_t dev, int ofs, uint16_t val) -{ - uint32_t v; - int retval; - - if (ofs & 1) - return PCISTS_EINVAL; - - retval = at697pci_cfg_r32(dev, ofs & ~0x3, &v); - if (retval != PCISTS_OK) - return retval; - - v = (v & ~(0xffff << (8*(ofs&3)))) | ((0xffff&val) << (8*(ofs&3))); - - return at697pci_cfg_w32(dev, ofs & ~0x3, v); -} - -static int at697pci_cfg_w8(pci_dev_t dev, int ofs, uint8_t val) -{ - uint32_t v; - - at697pci_cfg_r32(dev, ofs & ~0x3, &v); - - v = (v & ~(0xff << (8*(ofs&3)))) | ((0xff&val) << (8*(ofs&3))); - - return at697pci_cfg_w32(dev, ofs & ~0x3, v); -} - -/* Return the assigned system IRQ number that corresponds to the PCI - * "Interrupt Pin" information from configuration space. - * - * The IRQ information is stored in the at697_pci_irq_table configurable - * by the user. - * - * Returns the "system IRQ" for the PCI INTA#..INTD# pin in irq_pin. Returns - * 0xff if not assigned. - */ -static uint8_t at697pci_bus0_irq_map(pci_dev_t dev, int irq_pin) -{ - uint8_t sysIrqNr = 0; /* not assigned */ - int irq_group; - - if ( (irq_pin >= 1) && (irq_pin <= 4) ) { - /* Use default IRQ decoding on PCI BUS0 according slot numbering */ - irq_group = PCI_DEV_SLOT(dev) & 0x3; - irq_pin = ((irq_pin - 1) + irq_group) & 0x3; - /* Valid PCI "Interrupt Pin" number */ - sysIrqNr = at697_pci_irq_table[irq_pin]; - } - return sysIrqNr; -} - -static int at697pci_translate(uint32_t *address, int type, int dir) -{ - /* No address translation implmented at this point */ - return 0; -} - -extern struct pci_memreg_ops pci_memreg_sparc_be_ops; - -/* AT697 Big-Endian PCI access routines */ -static struct pci_access_drv at697pci_access_drv = { - .cfg = - { - at697pci_cfg_r8, - at697pci_cfg_r16, - at697pci_cfg_r32, - at697pci_cfg_w8, - at697pci_cfg_w16, - at697pci_cfg_w32, - }, - .io = - { /* AT697 only supports non-standard Big-Endian PCI Bus */ - _ld8, - _ld_be16, - _ld_be32, - _st8, - _st_be16, - _st_be32, - - }, - .memreg = &pci_memreg_sparc_be_ops, - .translate = at697pci_translate, -}; - -/* Initializes the AT697PCI core hardware - * - */ -static int at697pci_hw_init(struct at697pci_priv *priv) -{ - struct at697pci_regs *regs = priv->regs; - unsigned short vendor = regs->pciid1 >> 16; - - /* Must match ATMEL or ESA ID */ - if ( !((vendor == 0x1202) || (vendor == 0x1E0F)) ) { - /* No AT697 PCI, quit */ - return -1; - } - - /* If not in system slot we are not host and we must abort. - * This is a host only driver. - */ - if ((regs->pciis & 0x1000) != 0) { - return -1; - } - - /* Reset PCI Core */ - regs->pciic = 0xffffffff; - - /* Mask PCI interrupts */ - regs->pciite = 0; - - /* Map parts of AT697 main memory into PCI (for DMA) */ - regs->mbar1 = priv->bar1_pci_adr; - regs->mbar2 = priv->bar2_pci_adr; - regs->pcitpa = (priv->bar1_pci_adr & 0xff000000) | - ((priv->bar2_pci_adr>>16) & 0xff00); - - /* Enable PCI master and target memory command response */ - regs->pcisc |= 0x40 | 0x6; - - /* Set latency timer to 64 */ - regs->pcibhlc = 0x00004000; - - /* Set Inititator configuration so that AHB slave accesses generate memory read/write commands */ - regs->pciic = 0x41; - - return 0; -} - -/* Initializes the AT697PCI core and driver, must be called before calling init_pci() - * - * Return values - * 0 Successful initalization - * -1 Error during initialization. - */ -static int at697pci_init(struct at697pci_priv *priv) -{ - int pin; - union drvmgr_key_value *value; - char keyname_sysirq[6]; - char keyname_pio[10]; - - /* PCI core, init private structure */ - priv->regs = (struct at697pci_regs *) AT697_PCI_REG_ADR; - - /* Init PCI interrupt assignment table to all use the interrupt routed - * through the GPIO core. - * - * INT[A..D]# selects system IRQ (and I/O interrupt) - * INT[A..D]#_PIO selects PIO used to generate I/O interrupt - */ - strcpy(keyname_sysirq, "INTX#"); - strcpy(keyname_pio, "INTX#_PIO"); - for (pin=1; pin<5; pin++) { - if ( at697_pci_irq_table[pin-1] == 0xff ) { - /* User may override hardcoded IRQ setup */ - keyname_sysirq[3] = 'A' + (pin-1); - value = drvmgr_dev_key_get(priv->dev, - keyname_sysirq, DRVMGR_KT_INT); - if ( value ) - at697_pci_irq_table[pin-1] = value->i; - } - if ( at697_pci_irq_pio_table[pin-1] == 0xff ) { - /* User may override hardcoded IRQ setup */ - keyname_pio[3] = 'A' + (pin-1); - value = drvmgr_dev_key_get(priv->dev, - keyname_pio, DRVMGR_KT_INT); - if ( value ) - at697_pci_irq_pio_table[pin-1] = value->i; - } - } - - /* Use GRPCI target BAR1 and BAR2 to map CPU RAM to PCI, this is to - * make it possible for PCI peripherals to do DMA directly to CPU memory - * - * Defualt is to map system RAM at pci address 0x40000000 and system - * SDRAM to pci address 0x60000000 - */ - value = drvmgr_dev_key_get(priv->dev, "tgtbar1", DRVMGR_KT_INT); - if (value) - priv->bar1_pci_adr = value->i; - else - priv->bar1_pci_adr = SYSTEM_MAINMEM_START; /* default */ - - value = drvmgr_dev_key_get(priv->dev, "tgtbar2", DRVMGR_KT_INT); - if (value) - priv->bar2_pci_adr = value->i; - else - priv->bar2_pci_adr = SYSTEM_MAINMEM_START2; /* default */ - - /* Init the PCI Core */ - if ( at697pci_hw_init(priv) ) { - return -3; - } - - /* Down streams translation table */ - priv->maps_down[0].name = "AMBA -> PCI MEM Window"; - priv->maps_down[0].size = 0xF0000000 - 0xA0000000; - priv->maps_down[0].from_adr = (void *)0xA0000000; - priv->maps_down[0].to_adr = (void *)0xA0000000; - /* End table */ - priv->maps_down[1].size = 0; - - /* Up streams translation table, 2x16Mb mapped 1:1 */ - priv->maps_up[0].name = "Target BAR0 -> AMBA"; - priv->maps_up[0].size = 0x01000000; /* 16Mb BAR1 */ - priv->maps_up[0].from_adr = (void *)priv->bar1_pci_adr; - priv->maps_up[0].to_adr = (void *)priv->bar1_pci_adr; - priv->maps_up[1].name = "Target BAR1 -> AMBA"; - priv->maps_up[1].size = 0x01000000; /* 16Mb BAR2 */ - priv->maps_up[1].from_adr = (void *)priv->bar2_pci_adr; - priv->maps_up[1].to_adr = (void *)priv->bar2_pci_adr; - /* End table */ - priv->maps_up[2].size = 0; - - return 0; -} - -/* Called when a core is found with the AMBA device and vendor ID - * given in at697pci_ids[]. - */ -int at697pci_init1(struct drvmgr_dev *dev) -{ - struct at697pci_priv *priv; - struct pci_auto_setup at697pci_auto_cfg; - - DBG("AT697PCI[%d] on bus %s\n", dev->minor_drv, - dev->parent->dev->name); - - if ( at697pci_minor != 0 ) { - DBG("Driver only supports one PCI core\n"); - return DRVMGR_FAIL; - } - - at697pcipriv = priv = dev->priv; - if ( !priv ) - return DRVMGR_NOMEM; - - priv->dev = dev; - priv->minor = at697pci_minor++; - - if (at697pci_init(priv)) { - DBG("Failed to initialize at697pci driver\n"); - return DRVMGR_EIO; - } - - /* Host is always Big-Endian */ - pci_endian = PCI_BIG_ENDIAN; - - if (pci_access_drv_register(&at697pci_access_drv)) { - /* Access routines registration failed */ - return DRVMGR_FAIL; - } - - /* Prepare memory MAP */ - at697pci_auto_cfg.options = 0; - at697pci_auto_cfg.mem_start = 0; - at697pci_auto_cfg.mem_size = 0; - at697pci_auto_cfg.memio_start = PCI_MEM_START; - at697pci_auto_cfg.memio_size = PCI_MEM_SIZE; - at697pci_auto_cfg.io_start = 0; - at697pci_auto_cfg.io_size = 0; - at697pci_auto_cfg.irq_map = at697pci_bus0_irq_map; - at697pci_auto_cfg.irq_route = NULL; /* use standard routing */ - pci_config_register(&at697pci_auto_cfg); - - if (pci_config_init()) { - /* PCI configuration failed */ - return DRVMGR_FAIL; - } - - priv->config.maps_down = &priv->maps_down[0]; - priv->config.maps_up = &priv->maps_up[0]; - return pcibus_register(dev, &priv->config); -} - -int at697pci_init2(struct drvmgr_dev *dev) -{ -#if 0 - struct at697pci_priv *priv = dev->priv; -#endif - int pin, irq, pio, ioport; - LEON_Register_Map *regs = (LEON_Register_Map *)0x80000000; - - /* Enable interrupts now that init1 has been reached for all devices - * on the bus. - */ - - for (pin=1; pin<5; pin++) { - irq = at697_pci_irq_table[pin-1]; - pio = at697_pci_irq_pio_table[pin-1]; - if ( (pio < 16) && (irq >= 4) && (irq <= 7) ) { - /* AT697 I/O IRQ, we know how to set up this - * - * IRQ 4 -> I/O 0 - * IRQ 5 -> I/O 1 - * IRQ 6 -> I/O 2 - * IRQ 7 -> I/O 3 - */ - ioport = irq - 4; - - /* First disable interrupts */ - regs->PIO_Interrupt &= ~(0xff << (ioport * 8)); - /* Set PIO as input pin */ - regs->PIO_Direction &= ~(1 << pio); - /* Set Low Level sensitivity */ - regs->PIO_Interrupt |= ((0x80 | pio) << (ioport * 8)); - } - } - - /* Unmask Interrupt */ - /*priv->regs->pciite = 0xff;*/ - - return DRVMGR_OK; -} -- cgit v1.2.3