diff options
Diffstat (limited to 'ANDROID_3.4.5/arch/sparc/kernel/leon_pci_grpci2.c')
-rw-r--r-- | ANDROID_3.4.5/arch/sparc/kernel/leon_pci_grpci2.c | 897 |
1 files changed, 0 insertions, 897 deletions
diff --git a/ANDROID_3.4.5/arch/sparc/kernel/leon_pci_grpci2.c b/ANDROID_3.4.5/arch/sparc/kernel/leon_pci_grpci2.c deleted file mode 100644 index b1bc3885..00000000 --- a/ANDROID_3.4.5/arch/sparc/kernel/leon_pci_grpci2.c +++ /dev/null @@ -1,897 +0,0 @@ -/* - * leon_pci_grpci2.c: GRPCI2 Host PCI driver - * - * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom - * - */ - -#include <linux/of_device.h> -#include <linux/kernel.h> -#include <linux/pci.h> -#include <linux/delay.h> -#include <linux/export.h> -#include <asm/io.h> -#include <asm/leon.h> -#include <asm/vaddrs.h> -#include <asm/sections.h> -#include <asm/leon_pci.h> - -#include "irq.h" - -struct grpci2_barcfg { - unsigned long pciadr; /* PCI Space Address */ - unsigned long ahbadr; /* PCI Base address mapped to this AHB addr */ -}; - -/* Device Node Configuration options: - * - barcfgs : Custom Configuration of Host's 6 target BARs - * - irq_mask : Limit which PCI interrupts are enabled - * - do_reset : Force PCI Reset on startup - * - * barcfgs - * ======= - * - * Optional custom Target BAR configuration (see struct grpci2_barcfg). All - * addresses are physical. Array always contains 6 elements (len=2*4*6 bytes) - * - * -1 means not configured (let host driver do default setup). - * - * [i*2+0] = PCI Address of BAR[i] on target interface - * [i*2+1] = Accessing PCI address of BAR[i] result in this AMBA address - * - * - * irq_mask - * ======== - * - * Limit which PCI interrupts are enabled. 0=Disable, 1=Enable. By default - * all are enabled. Use this when PCI interrupt pins are floating on PCB. - * int, len=4. - * bit0 = PCI INTA# - * bit1 = PCI INTB# - * bit2 = PCI INTC# - * bit3 = PCI INTD# - * - * - * reset - * ===== - * - * Force PCI reset on startup. int, len=4 - */ - -/* Enable Debugging Configuration Space Access */ -#undef GRPCI2_DEBUG_CFGACCESS - -/* - * GRPCI2 APB Register MAP - */ -struct grpci2_regs { - unsigned int ctrl; /* 0x00 Control */ - unsigned int sts_cap; /* 0x04 Status / Capabilities */ - int res1; /* 0x08 */ - unsigned int io_map; /* 0x0C I/O Map address */ - unsigned int dma_ctrl; /* 0x10 DMA */ - unsigned int dma_bdbase; /* 0x14 DMA */ - int res2[2]; /* 0x18 */ - unsigned int bars[6]; /* 0x20 read-only PCI BARs */ - int res3[2]; /* 0x38 */ - unsigned int ahbmst_map[16]; /* 0x40 AHB->PCI Map per AHB Master */ - - /* PCI Trace Buffer Registers (OPTIONAL) */ - unsigned int t_ctrl; /* 0x80 */ - unsigned int t_cnt; /* 0x84 */ - unsigned int t_adpat; /* 0x88 */ - unsigned int t_admask; /* 0x8C */ - unsigned int t_sigpat; /* 0x90 */ - unsigned int t_sigmask; /* 0x94 */ - unsigned int t_adstate; /* 0x98 */ - unsigned int t_sigstate; /* 0x9C */ -}; - -#define REGLOAD(a) (be32_to_cpu(__raw_readl(&(a)))) -#define REGSTORE(a, v) (__raw_writel(cpu_to_be32(v), &(a))) - -#define CTRL_BUS_BIT 16 - -#define CTRL_RESET (1<<31) -#define CTRL_SI (1<<27) -#define CTRL_PE (1<<26) -#define CTRL_EI (1<<25) -#define CTRL_ER (1<<24) -#define CTRL_BUS (0xff<<CTRL_BUS_BIT) -#define CTRL_HOSTINT 0xf - -#define STS_HOST_BIT 31 -#define STS_MST_BIT 30 -#define STS_TAR_BIT 29 -#define STS_DMA_BIT 28 -#define STS_DI_BIT 27 -#define STS_HI_BIT 26 -#define STS_IRQMODE_BIT 24 -#define STS_TRACE_BIT 23 -#define STS_CFGERRVALID_BIT 20 -#define STS_CFGERR_BIT 19 -#define STS_INTTYPE_BIT 12 -#define STS_INTSTS_BIT 8 -#define STS_FDEPTH_BIT 2 -#define STS_FNUM_BIT 0 - -#define STS_HOST (1<<STS_HOST_BIT) -#define STS_MST (1<<STS_MST_BIT) -#define STS_TAR (1<<STS_TAR_BIT) -#define STS_DMA (1<<STS_DMA_BIT) -#define STS_DI (1<<STS_DI_BIT) -#define STS_HI (1<<STS_HI_BIT) -#define STS_IRQMODE (0x3<<STS_IRQMODE_BIT) -#define STS_TRACE (1<<STS_TRACE_BIT) -#define STS_CFGERRVALID (1<<STS_CFGERRVALID_BIT) -#define STS_CFGERR (1<<STS_CFGERR_BIT) -#define STS_INTTYPE (0x3f<<STS_INTTYPE_BIT) -#define STS_INTSTS (0xf<<STS_INTSTS_BIT) -#define STS_FDEPTH (0x7<<STS_FDEPTH_BIT) -#define STS_FNUM (0x3<<STS_FNUM_BIT) - -#define STS_ISYSERR (1<<17) -#define STS_IDMA (1<<16) -#define STS_IDMAERR (1<<15) -#define STS_IMSTABRT (1<<14) -#define STS_ITGTABRT (1<<13) -#define STS_IPARERR (1<<12) - -#define STS_ERR_IRQ (STS_ISYSERR | STS_IMSTABRT | STS_ITGTABRT | STS_IPARERR) - -struct grpci2_bd_chan { - unsigned int ctrl; /* 0x00 DMA Control */ - unsigned int nchan; /* 0x04 Next DMA Channel Address */ - unsigned int nbd; /* 0x08 Next Data Descriptor in chan */ - unsigned int res; /* 0x0C Reserved */ -}; - -#define BD_CHAN_EN 0x80000000 -#define BD_CHAN_TYPE 0x00300000 -#define BD_CHAN_BDCNT 0x0000ffff -#define BD_CHAN_EN_BIT 31 -#define BD_CHAN_TYPE_BIT 20 -#define BD_CHAN_BDCNT_BIT 0 - -struct grpci2_bd_data { - unsigned int ctrl; /* 0x00 DMA Data Control */ - unsigned int pci_adr; /* 0x04 PCI Start Address */ - unsigned int ahb_adr; /* 0x08 AHB Start address */ - unsigned int next; /* 0x0C Next Data Descriptor in chan */ -}; - -#define BD_DATA_EN 0x80000000 -#define BD_DATA_IE 0x40000000 -#define BD_DATA_DR 0x20000000 -#define BD_DATA_TYPE 0x00300000 -#define BD_DATA_ER 0x00080000 -#define BD_DATA_LEN 0x0000ffff -#define BD_DATA_EN_BIT 31 -#define BD_DATA_IE_BIT 30 -#define BD_DATA_DR_BIT 29 -#define BD_DATA_TYPE_BIT 20 -#define BD_DATA_ER_BIT 19 -#define BD_DATA_LEN_BIT 0 - -/* GRPCI2 Capability */ -struct grpci2_cap_first { - unsigned int ctrl; - unsigned int pci2ahb_map[6]; - unsigned int ext2ahb_map; - unsigned int io_map; - unsigned int pcibar_size[6]; -}; -#define CAP9_CTRL_OFS 0 -#define CAP9_BAR_OFS 0x4 -#define CAP9_IOMAP_OFS 0x20 -#define CAP9_BARSIZE_OFS 0x24 - -struct grpci2_priv { - struct leon_pci_info info; /* must be on top of this structure */ - struct grpci2_regs *regs; - char irq; - char irq_mode; /* IRQ Mode from CAPSTS REG */ - char bt_enabled; - char do_reset; - char irq_mask; - u32 pciid; /* PCI ID of Host */ - unsigned char irq_map[4]; - - /* Virtual IRQ numbers */ - unsigned int virq_err; - unsigned int virq_dma; - - /* AHB PCI Windows */ - unsigned long pci_area; /* MEMORY */ - unsigned long pci_area_end; - unsigned long pci_io; /* I/O */ - unsigned long pci_conf; /* CONFIGURATION */ - unsigned long pci_conf_end; - unsigned long pci_io_va; - - struct grpci2_barcfg tgtbars[6]; -}; - -DEFINE_SPINLOCK(grpci2_dev_lock); -struct grpci2_priv *grpci2priv; - -int grpci2_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{ - struct grpci2_priv *priv = dev->bus->sysdata; - int irq_group; - - /* Use default IRQ decoding on PCI BUS0 according slot numbering */ - irq_group = slot & 0x3; - pin = ((pin - 1) + irq_group) & 0x3; - - return priv->irq_map[pin]; -} - -static int grpci2_cfg_r32(struct grpci2_priv *priv, unsigned int bus, - unsigned int devfn, int where, u32 *val) -{ - unsigned int *pci_conf; - unsigned long flags; - u32 tmp; - - if (where & 0x3) - return -EINVAL; - - if (bus == 0 && PCI_SLOT(devfn) != 0) - devfn += (0x8 * 6); - - /* Select bus */ - spin_lock_irqsave(&grpci2_dev_lock, flags); - REGSTORE(priv->regs->ctrl, (REGLOAD(priv->regs->ctrl) & ~(0xff << 16)) | - (bus << 16)); - spin_unlock_irqrestore(&grpci2_dev_lock, flags); - - /* clear old status */ - REGSTORE(priv->regs->sts_cap, (STS_CFGERR | STS_CFGERRVALID)); - - pci_conf = (unsigned int *) (priv->pci_conf | - (devfn << 8) | (where & 0xfc)); - tmp = LEON3_BYPASS_LOAD_PA(pci_conf); - - /* Wait until GRPCI2 signals that CFG access is done, it should be - * done instantaneously unless a DMA operation is ongoing... - */ - while ((REGLOAD(priv->regs->sts_cap) & STS_CFGERRVALID) == 0) - ; - - if (REGLOAD(priv->regs->sts_cap) & STS_CFGERR) { - *val = 0xffffffff; - } else { - /* Bus always little endian (unaffected by byte-swapping) */ - *val = flip_dword(tmp); - } - - return 0; -} - -static int grpci2_cfg_r16(struct grpci2_priv *priv, unsigned int bus, - unsigned int devfn, int where, u32 *val) -{ - u32 v; - int ret; - - if (where & 0x1) - return -EINVAL; - ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v); - *val = 0xffff & (v >> (8 * (where & 0x3))); - return ret; -} - -static int grpci2_cfg_r8(struct grpci2_priv *priv, unsigned int bus, - unsigned int devfn, int where, u32 *val) -{ - u32 v; - int ret; - - ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v); - *val = 0xff & (v >> (8 * (where & 3))); - - return ret; -} - -static int grpci2_cfg_w32(struct grpci2_priv *priv, unsigned int bus, - unsigned int devfn, int where, u32 val) -{ - unsigned int *pci_conf; - unsigned long flags; - - if (where & 0x3) - return -EINVAL; - - if (bus == 0 && PCI_SLOT(devfn) != 0) - devfn += (0x8 * 6); - - /* Select bus */ - spin_lock_irqsave(&grpci2_dev_lock, flags); - REGSTORE(priv->regs->ctrl, (REGLOAD(priv->regs->ctrl) & ~(0xff << 16)) | - (bus << 16)); - spin_unlock_irqrestore(&grpci2_dev_lock, flags); - - /* clear old status */ - REGSTORE(priv->regs->sts_cap, (STS_CFGERR | STS_CFGERRVALID)); - - pci_conf = (unsigned int *) (priv->pci_conf | - (devfn << 8) | (where & 0xfc)); - LEON3_BYPASS_STORE_PA(pci_conf, flip_dword(val)); - - /* Wait until GRPCI2 signals that CFG access is done, it should be - * done instantaneously unless a DMA operation is ongoing... - */ - while ((REGLOAD(priv->regs->sts_cap) & STS_CFGERRVALID) == 0) - ; - - return 0; -} - -static int grpci2_cfg_w16(struct grpci2_priv *priv, unsigned int bus, - unsigned int devfn, int where, u32 val) -{ - int ret; - u32 v; - - if (where & 0x1) - return -EINVAL; - ret = grpci2_cfg_r32(priv, bus, devfn, where&~3, &v); - if (ret) - return ret; - v = (v & ~(0xffff << (8 * (where & 0x3)))) | - ((0xffff & val) << (8 * (where & 0x3))); - return grpci2_cfg_w32(priv, bus, devfn, where & ~0x3, v); -} - -static int grpci2_cfg_w8(struct grpci2_priv *priv, unsigned int bus, - unsigned int devfn, int where, u32 val) -{ - int ret; - u32 v; - - ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v); - if (ret != 0) - return ret; - v = (v & ~(0xff << (8 * (where & 0x3)))) | - ((0xff & val) << (8 * (where & 0x3))); - return grpci2_cfg_w32(priv, bus, devfn, where & ~0x3, v); -} - -/* Read from Configuration Space. When entering here the PCI layer has taken - * the pci_lock spinlock and IRQ is off. - */ -static int grpci2_read_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 *val) -{ - struct grpci2_priv *priv = grpci2priv; - unsigned int busno = bus->number; - int ret; - - if (PCI_SLOT(devfn) > 15 || (PCI_SLOT(devfn) == 0 && busno == 0)) { - *val = ~0; - return 0; - } - - switch (size) { - case 1: - ret = grpci2_cfg_r8(priv, busno, devfn, where, val); - break; - case 2: - ret = grpci2_cfg_r16(priv, busno, devfn, where, val); - break; - case 4: - ret = grpci2_cfg_r32(priv, busno, devfn, where, val); - break; - default: - ret = -EINVAL; - break; - } - -#ifdef GRPCI2_DEBUG_CFGACCESS - printk(KERN_INFO "grpci2_read_config: [%02x:%02x:%x] ofs=%d val=%x " - "size=%d\n", busno, PCI_SLOT(devfn), PCI_FUNC(devfn), where, - *val, size); -#endif - - return ret; -} - -/* Write to Configuration Space. When entering here the PCI layer has taken - * the pci_lock spinlock and IRQ is off. - */ -static int grpci2_write_config(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 val) -{ - struct grpci2_priv *priv = grpci2priv; - unsigned int busno = bus->number; - - if (PCI_SLOT(devfn) > 15 || (PCI_SLOT(devfn) == 0 && busno == 0)) - return 0; - -#ifdef GRPCI2_DEBUG_CFGACCESS - printk(KERN_INFO "grpci2_write_config: [%02x:%02x:%x] ofs=%d size=%d " - "val=%x\n", busno, PCI_SLOT(devfn), PCI_FUNC(devfn), - where, size, val); -#endif - - switch (size) { - default: - return -EINVAL; - case 1: - return grpci2_cfg_w8(priv, busno, devfn, where, val); - case 2: - return grpci2_cfg_w16(priv, busno, devfn, where, val); - case 4: - return grpci2_cfg_w32(priv, busno, devfn, where, val); - } -} - -static struct pci_ops grpci2_ops = { - .read = grpci2_read_config, - .write = grpci2_write_config, -}; - -/* GENIRQ IRQ chip implementation for GRPCI2 irqmode=0..2. In configuration - * 3 where all PCI Interrupts has a separate IRQ on the system IRQ controller - * this is not needed and the standard IRQ controller can be used. - */ - -static void grpci2_mask_irq(struct irq_data *data) -{ - unsigned long flags; - unsigned int irqidx; - struct grpci2_priv *priv = grpci2priv; - - irqidx = (unsigned int)data->chip_data - 1; - if (irqidx > 3) /* only mask PCI interrupts here */ - return; - - spin_lock_irqsave(&grpci2_dev_lock, flags); - REGSTORE(priv->regs->ctrl, REGLOAD(priv->regs->ctrl) & ~(1 << irqidx)); - spin_unlock_irqrestore(&grpci2_dev_lock, flags); -} - -static void grpci2_unmask_irq(struct irq_data *data) -{ - unsigned long flags; - unsigned int irqidx; - struct grpci2_priv *priv = grpci2priv; - - irqidx = (unsigned int)data->chip_data - 1; - if (irqidx > 3) /* only unmask PCI interrupts here */ - return; - - spin_lock_irqsave(&grpci2_dev_lock, flags); - REGSTORE(priv->regs->ctrl, REGLOAD(priv->regs->ctrl) | (1 << irqidx)); - spin_unlock_irqrestore(&grpci2_dev_lock, flags); -} - -static unsigned int grpci2_startup_irq(struct irq_data *data) -{ - grpci2_unmask_irq(data); - return 0; -} - -static void grpci2_shutdown_irq(struct irq_data *data) -{ - grpci2_mask_irq(data); -} - -static struct irq_chip grpci2_irq = { - .name = "grpci2", - .irq_startup = grpci2_startup_irq, - .irq_shutdown = grpci2_shutdown_irq, - .irq_mask = grpci2_mask_irq, - .irq_unmask = grpci2_unmask_irq, -}; - -/* Handle one or multiple IRQs from the PCI core */ -static void grpci2_pci_flow_irq(unsigned int irq, struct irq_desc *desc) -{ - struct grpci2_priv *priv = grpci2priv; - int i, ack = 0; - unsigned int ctrl, sts_cap, pci_ints; - - ctrl = REGLOAD(priv->regs->ctrl); - sts_cap = REGLOAD(priv->regs->sts_cap); - - /* Error Interrupt? */ - if (sts_cap & STS_ERR_IRQ) { - generic_handle_irq(priv->virq_err); - ack = 1; - } - - /* PCI Interrupt? */ - pci_ints = ((~sts_cap) >> STS_INTSTS_BIT) & ctrl & CTRL_HOSTINT; - if (pci_ints) { - /* Call respective PCI Interrupt handler */ - for (i = 0; i < 4; i++) { - if (pci_ints & (1 << i)) - generic_handle_irq(priv->irq_map[i]); - } - ack = 1; - } - - /* - * Decode DMA Interrupt only when shared with Err and PCI INTX#, when - * the DMA is a unique IRQ the DMA interrupts doesn't end up here, they - * goes directly to DMA ISR. - */ - if ((priv->irq_mode == 0) && (sts_cap & (STS_IDMA | STS_IDMAERR))) { - generic_handle_irq(priv->virq_dma); - ack = 1; - } - - /* - * Call "first level" IRQ chip end-of-irq handler. It will ACK LEON IRQ - * Controller, this must be done after IRQ sources have been handled to - * avoid double IRQ generation - */ - if (ack) - desc->irq_data.chip->irq_eoi(&desc->irq_data); -} - -/* Create a virtual IRQ */ -static unsigned int grpci2_build_device_irq(unsigned int irq) -{ - unsigned int virq = 0, pil; - - pil = 1 << 8; - virq = irq_alloc(irq, pil); - if (virq == 0) - goto out; - - irq_set_chip_and_handler_name(virq, &grpci2_irq, handle_simple_irq, - "pcilvl"); - irq_set_chip_data(virq, (void *)irq); - -out: - return virq; -} - -void grpci2_hw_init(struct grpci2_priv *priv) -{ - u32 ahbadr, pciadr, bar_sz, capptr, io_map, data; - struct grpci2_regs *regs = priv->regs; - int i; - struct grpci2_barcfg *barcfg = priv->tgtbars; - - /* Reset any earlier setup */ - if (priv->do_reset) { - printk(KERN_INFO "GRPCI2: Resetting PCI bus\n"); - REGSTORE(regs->ctrl, CTRL_RESET); - ssleep(1); /* Wait for boards to settle */ - } - REGSTORE(regs->ctrl, 0); - REGSTORE(regs->sts_cap, ~0); /* Clear Status */ - REGSTORE(regs->dma_ctrl, 0); - REGSTORE(regs->dma_bdbase, 0); - - /* Translate I/O accesses to 0, I/O Space always @ PCI low 64Kbytes */ - REGSTORE(regs->io_map, REGLOAD(regs->io_map) & 0x0000ffff); - - /* set 1:1 mapping between AHB -> PCI memory space, for all Masters - * Each AHB master has it's own mapping registers. Max 16 AHB masters. - */ - for (i = 0; i < 16; i++) - REGSTORE(regs->ahbmst_map[i], priv->pci_area); - - /* Get the GRPCI2 Host PCI ID */ - grpci2_cfg_r32(priv, 0, 0, PCI_VENDOR_ID, &priv->pciid); - - /* Get address to first (always defined) capability structure */ - grpci2_cfg_r8(priv, 0, 0, PCI_CAPABILITY_LIST, &capptr); - - /* Enable/Disable Byte twisting */ - grpci2_cfg_r32(priv, 0, 0, capptr+CAP9_IOMAP_OFS, &io_map); - io_map = (io_map & ~0x1) | (priv->bt_enabled ? 1 : 0); - grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_IOMAP_OFS, io_map); - - /* Setup the Host's PCI Target BARs for other peripherals to access, - * and do DMA to the host's memory. The target BARs can be sized and - * enabled individually. - * - * User may set custom target BARs, but default is: - * The first BARs is used to map kernel low (DMA is part of normal - * region on sparc which is SRMMU_MAXMEM big) main memory 1:1 to the - * PCI bus, the other BARs are disabled. We assume that the first BAR - * is always available. - */ - for (i = 0; i < 6; i++) { - if (barcfg[i].pciadr != ~0 && barcfg[i].ahbadr != ~0) { - /* Target BARs must have the proper alignment */ - ahbadr = barcfg[i].ahbadr; - pciadr = barcfg[i].pciadr; - bar_sz = ((pciadr - 1) & ~pciadr) + 1; - } else { - if (i == 0) { - /* Map main memory */ - bar_sz = 0xf0000008; /* 256MB prefetchable */ - ahbadr = 0xf0000000 & (u32)__pa(PAGE_ALIGN( - (unsigned long) &_end)); - pciadr = ahbadr; - } else { - bar_sz = 0; - ahbadr = 0; - pciadr = 0; - } - } - grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_BARSIZE_OFS+i*4, bar_sz); - grpci2_cfg_w32(priv, 0, 0, PCI_BASE_ADDRESS_0+i*4, pciadr); - grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_BAR_OFS+i*4, ahbadr); - printk(KERN_INFO " TGT BAR[%d]: 0x%08x (PCI)-> 0x%08x\n", - i, pciadr, ahbadr); - } - - /* set as bus master and enable pci memory responses */ - grpci2_cfg_r32(priv, 0, 0, PCI_COMMAND, &data); - data |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - grpci2_cfg_w32(priv, 0, 0, PCI_COMMAND, data); - - /* Enable Error respone (CPU-TRAP) on illegal memory access. */ - REGSTORE(regs->ctrl, CTRL_ER | CTRL_PE); -} - -static irqreturn_t grpci2_jump_interrupt(int irq, void *arg) -{ - printk(KERN_ERR "GRPCI2: Jump IRQ happened\n"); - return IRQ_NONE; -} - -/* Handle GRPCI2 Error Interrupt */ -static irqreturn_t grpci2_err_interrupt(int irq, void *arg) -{ - struct grpci2_priv *priv = arg; - struct grpci2_regs *regs = priv->regs; - unsigned int status; - - status = REGLOAD(regs->sts_cap); - if ((status & STS_ERR_IRQ) == 0) - return IRQ_NONE; - - if (status & STS_IPARERR) - printk(KERN_ERR "GRPCI2: Parity Error\n"); - - if (status & STS_ITGTABRT) - printk(KERN_ERR "GRPCI2: Target Abort\n"); - - if (status & STS_IMSTABRT) - printk(KERN_ERR "GRPCI2: Master Abort\n"); - - if (status & STS_ISYSERR) - printk(KERN_ERR "GRPCI2: System Error\n"); - - /* Clear handled INT TYPE IRQs */ - REGSTORE(regs->sts_cap, status & STS_ERR_IRQ); - - return IRQ_HANDLED; -} - -static int __devinit grpci2_of_probe(struct platform_device *ofdev) -{ - struct grpci2_regs *regs; - struct grpci2_priv *priv; - int err, i, len; - const int *tmp; - unsigned int capability; - - if (grpci2priv) { - printk(KERN_ERR "GRPCI2: only one GRPCI2 core supported\n"); - return -ENODEV; - } - - if (ofdev->num_resources < 3) { - printk(KERN_ERR "GRPCI2: not enough APB/AHB resources\n"); - return -EIO; - } - - /* Find Device Address */ - regs = of_ioremap(&ofdev->resource[0], 0, - resource_size(&ofdev->resource[0]), - "grlib-grpci2 regs"); - if (regs == NULL) { - printk(KERN_ERR "GRPCI2: ioremap failed\n"); - return -EIO; - } - - /* - * Check that we're in Host Slot and that we can act as a Host Bridge - * and not only as target. - */ - capability = REGLOAD(regs->sts_cap); - if ((capability & STS_HOST) || !(capability & STS_MST)) { - printk(KERN_INFO "GRPCI2: not in host system slot\n"); - err = -EIO; - goto err1; - } - - priv = grpci2priv = kzalloc(sizeof(struct grpci2_priv), GFP_KERNEL); - if (grpci2priv == NULL) { - err = -ENOMEM; - goto err1; - } - memset(grpci2priv, 0, sizeof(*grpci2priv)); - priv->regs = regs; - priv->irq = ofdev->archdata.irqs[0]; /* BASE IRQ */ - priv->irq_mode = (capability & STS_IRQMODE) >> STS_IRQMODE_BIT; - - printk(KERN_INFO "GRPCI2: host found at %p, irq%d\n", regs, priv->irq); - - /* Byte twisting should be made configurable from kernel command line */ - priv->bt_enabled = 1; - - /* Let user do custom Target BAR assignment */ - tmp = of_get_property(ofdev->dev.of_node, "barcfg", &len); - if (tmp && (len == 2*4*6)) - memcpy(priv->tgtbars, tmp, 2*4*6); - else - memset(priv->tgtbars, -1, 2*4*6); - - /* Limit IRQ unmasking in irq_mode 2 and 3 */ - tmp = of_get_property(ofdev->dev.of_node, "irq_mask", &len); - if (tmp && (len == 4)) - priv->do_reset = *tmp; - else - priv->irq_mask = 0xf; - - /* Optional PCI reset. Force PCI reset on startup */ - tmp = of_get_property(ofdev->dev.of_node, "reset", &len); - if (tmp && (len == 4)) - priv->do_reset = *tmp; - else - priv->do_reset = 0; - - /* Find PCI Memory, I/O and Configuration Space Windows */ - priv->pci_area = ofdev->resource[1].start; - priv->pci_area_end = ofdev->resource[1].end+1; - priv->pci_io = ofdev->resource[2].start; - priv->pci_conf = ofdev->resource[2].start + 0x10000; - priv->pci_conf_end = priv->pci_conf + 0x10000; - priv->pci_io_va = (unsigned long)ioremap(priv->pci_io, 0x10000); - if (!priv->pci_io_va) { - err = -EIO; - goto err2; - } - - printk(KERN_INFO - "GRPCI2: MEMORY SPACE [0x%08lx - 0x%08lx]\n" - " I/O SPACE [0x%08lx - 0x%08lx]\n" - " CONFIG SPACE [0x%08lx - 0x%08lx]\n", - priv->pci_area, priv->pci_area_end-1, - priv->pci_io, priv->pci_conf-1, - priv->pci_conf, priv->pci_conf_end-1); - - /* - * I/O Space resources in I/O Window mapped into Virtual Adr Space - * We never use low 4KB because some devices seem have problems using - * address 0. - */ - memset(&priv->info.io_space, 0, sizeof(struct resource)); - priv->info.io_space.name = "GRPCI2 PCI I/O Space"; - priv->info.io_space.start = priv->pci_io_va + 0x1000; - priv->info.io_space.end = priv->pci_io_va + 0x10000 - 1; - priv->info.io_space.flags = IORESOURCE_IO; - - /* - * GRPCI2 has no prefetchable memory, map everything as - * non-prefetchable memory - */ - memset(&priv->info.mem_space, 0, sizeof(struct resource)); - priv->info.mem_space.name = "GRPCI2 PCI MEM Space"; - priv->info.mem_space.start = priv->pci_area; - priv->info.mem_space.end = priv->pci_area_end - 1; - priv->info.mem_space.flags = IORESOURCE_MEM; - - if (request_resource(&iomem_resource, &priv->info.mem_space) < 0) - goto err3; - if (request_resource(&ioport_resource, &priv->info.io_space) < 0) - goto err4; - - grpci2_hw_init(priv); - - /* - * Get PCI Interrupt to System IRQ mapping and setup IRQ handling - * Error IRQ always on PCI INTA. - */ - if (priv->irq_mode < 2) { - /* All PCI interrupts are shared using the same system IRQ */ - leon_update_virq_handling(priv->irq, grpci2_pci_flow_irq, - "pcilvl", 0); - - priv->irq_map[0] = grpci2_build_device_irq(1); - priv->irq_map[1] = grpci2_build_device_irq(2); - priv->irq_map[2] = grpci2_build_device_irq(3); - priv->irq_map[3] = grpci2_build_device_irq(4); - - priv->virq_err = grpci2_build_device_irq(5); - if (priv->irq_mode & 1) - priv->virq_dma = ofdev->archdata.irqs[1]; - else - priv->virq_dma = grpci2_build_device_irq(6); - - /* Enable IRQs on LEON IRQ controller */ - err = request_irq(priv->irq, grpci2_jump_interrupt, 0, - "GRPCI2_JUMP", priv); - if (err) - printk(KERN_ERR "GRPCI2: ERR IRQ request failed\n"); - } else { - /* All PCI interrupts have an unique IRQ interrupt */ - for (i = 0; i < 4; i++) { - /* Make LEON IRQ layer handle level IRQ by acking */ - leon_update_virq_handling(ofdev->archdata.irqs[i], - handle_fasteoi_irq, "pcilvl", - 1); - priv->irq_map[i] = ofdev->archdata.irqs[i]; - } - priv->virq_err = priv->irq_map[0]; - if (priv->irq_mode & 1) - priv->virq_dma = ofdev->archdata.irqs[4]; - else - priv->virq_dma = priv->irq_map[0]; - - /* Unmask all PCI interrupts, request_irq will not do that */ - REGSTORE(regs->ctrl, REGLOAD(regs->ctrl)|(priv->irq_mask&0xf)); - } - - /* Setup IRQ handler for non-configuration space access errors */ - err = request_irq(priv->virq_err, grpci2_err_interrupt, IRQF_SHARED, - "GRPCI2_ERR", priv); - if (err) { - printk(KERN_DEBUG "GRPCI2: ERR VIRQ request failed: %d\n", err); - goto err5; - } - - /* - * Enable Error Interrupts. PCI interrupts are unmasked once request_irq - * is called by the PCI Device drivers - */ - REGSTORE(regs->ctrl, REGLOAD(regs->ctrl) | CTRL_EI | CTRL_SI); - - /* Init common layer and scan buses */ - priv->info.ops = &grpci2_ops; - priv->info.map_irq = grpci2_map_irq; - leon_pci_init(ofdev, &priv->info); - - return 0; - -err5: - release_resource(&priv->info.io_space); -err4: - release_resource(&priv->info.mem_space); -err3: - err = -ENOMEM; - iounmap((void *)priv->pci_io_va); -err2: - kfree(priv); -err1: - of_iounmap(&ofdev->resource[0], regs, - resource_size(&ofdev->resource[0])); - return err; -} - -static struct of_device_id grpci2_of_match[] = { - { - .name = "GAISLER_GRPCI2", - }, - { - .name = "01_07c", - }, - {}, -}; - -static struct platform_driver grpci2_of_driver = { - .driver = { - .name = "grpci2", - .owner = THIS_MODULE, - .of_match_table = grpci2_of_match, - }, - .probe = grpci2_of_probe, -}; - -static int __init grpci2_init(void) -{ - return platform_driver_register(&grpci2_of_driver); -} - -subsys_initcall(grpci2_init); |