162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * leon_pci_grpci2.c: GRPCI2 Host PCI driver 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2011 Aeroflex Gaisler AB, Daniel Hellstrom 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/pci.h> 1162306a36Sopenharmony_ci#include <linux/slab.h> 1262306a36Sopenharmony_ci#include <linux/delay.h> 1362306a36Sopenharmony_ci#include <linux/export.h> 1462306a36Sopenharmony_ci#include <linux/of.h> 1562306a36Sopenharmony_ci#include <linux/platform_device.h> 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci#include <asm/io.h> 1862306a36Sopenharmony_ci#include <asm/leon.h> 1962306a36Sopenharmony_ci#include <asm/vaddrs.h> 2062306a36Sopenharmony_ci#include <asm/sections.h> 2162306a36Sopenharmony_ci#include <asm/leon_pci.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include "irq.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct grpci2_barcfg { 2662306a36Sopenharmony_ci unsigned long pciadr; /* PCI Space Address */ 2762306a36Sopenharmony_ci unsigned long ahbadr; /* PCI Base address mapped to this AHB addr */ 2862306a36Sopenharmony_ci}; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* Device Node Configuration options: 3162306a36Sopenharmony_ci * - barcfgs : Custom Configuration of Host's 6 target BARs 3262306a36Sopenharmony_ci * - irq_mask : Limit which PCI interrupts are enabled 3362306a36Sopenharmony_ci * - do_reset : Force PCI Reset on startup 3462306a36Sopenharmony_ci * 3562306a36Sopenharmony_ci * barcfgs 3662306a36Sopenharmony_ci * ======= 3762306a36Sopenharmony_ci * 3862306a36Sopenharmony_ci * Optional custom Target BAR configuration (see struct grpci2_barcfg). All 3962306a36Sopenharmony_ci * addresses are physical. Array always contains 6 elements (len=2*4*6 bytes) 4062306a36Sopenharmony_ci * 4162306a36Sopenharmony_ci * -1 means not configured (let host driver do default setup). 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * [i*2+0] = PCI Address of BAR[i] on target interface 4462306a36Sopenharmony_ci * [i*2+1] = Accessing PCI address of BAR[i] result in this AMBA address 4562306a36Sopenharmony_ci * 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci * irq_mask 4862306a36Sopenharmony_ci * ======== 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * Limit which PCI interrupts are enabled. 0=Disable, 1=Enable. By default 5162306a36Sopenharmony_ci * all are enabled. Use this when PCI interrupt pins are floating on PCB. 5262306a36Sopenharmony_ci * int, len=4. 5362306a36Sopenharmony_ci * bit0 = PCI INTA# 5462306a36Sopenharmony_ci * bit1 = PCI INTB# 5562306a36Sopenharmony_ci * bit2 = PCI INTC# 5662306a36Sopenharmony_ci * bit3 = PCI INTD# 5762306a36Sopenharmony_ci * 5862306a36Sopenharmony_ci * 5962306a36Sopenharmony_ci * reset 6062306a36Sopenharmony_ci * ===== 6162306a36Sopenharmony_ci * 6262306a36Sopenharmony_ci * Force PCI reset on startup. int, len=4 6362306a36Sopenharmony_ci */ 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci/* Enable Debugging Configuration Space Access */ 6662306a36Sopenharmony_ci#undef GRPCI2_DEBUG_CFGACCESS 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* 6962306a36Sopenharmony_ci * GRPCI2 APB Register MAP 7062306a36Sopenharmony_ci */ 7162306a36Sopenharmony_cistruct grpci2_regs { 7262306a36Sopenharmony_ci unsigned int ctrl; /* 0x00 Control */ 7362306a36Sopenharmony_ci unsigned int sts_cap; /* 0x04 Status / Capabilities */ 7462306a36Sopenharmony_ci int res1; /* 0x08 */ 7562306a36Sopenharmony_ci unsigned int io_map; /* 0x0C I/O Map address */ 7662306a36Sopenharmony_ci unsigned int dma_ctrl; /* 0x10 DMA */ 7762306a36Sopenharmony_ci unsigned int dma_bdbase; /* 0x14 DMA */ 7862306a36Sopenharmony_ci int res2[2]; /* 0x18 */ 7962306a36Sopenharmony_ci unsigned int bars[6]; /* 0x20 read-only PCI BARs */ 8062306a36Sopenharmony_ci int res3[2]; /* 0x38 */ 8162306a36Sopenharmony_ci unsigned int ahbmst_map[16]; /* 0x40 AHB->PCI Map per AHB Master */ 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* PCI Trace Buffer Registers (OPTIONAL) */ 8462306a36Sopenharmony_ci unsigned int t_ctrl; /* 0x80 */ 8562306a36Sopenharmony_ci unsigned int t_cnt; /* 0x84 */ 8662306a36Sopenharmony_ci unsigned int t_adpat; /* 0x88 */ 8762306a36Sopenharmony_ci unsigned int t_admask; /* 0x8C */ 8862306a36Sopenharmony_ci unsigned int t_sigpat; /* 0x90 */ 8962306a36Sopenharmony_ci unsigned int t_sigmask; /* 0x94 */ 9062306a36Sopenharmony_ci unsigned int t_adstate; /* 0x98 */ 9162306a36Sopenharmony_ci unsigned int t_sigstate; /* 0x9C */ 9262306a36Sopenharmony_ci}; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci#define REGLOAD(a) (be32_to_cpu(__raw_readl(&(a)))) 9562306a36Sopenharmony_ci#define REGSTORE(a, v) (__raw_writel(cpu_to_be32(v), &(a))) 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define CTRL_BUS_BIT 16 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci#define CTRL_RESET (1<<31) 10062306a36Sopenharmony_ci#define CTRL_SI (1<<27) 10162306a36Sopenharmony_ci#define CTRL_PE (1<<26) 10262306a36Sopenharmony_ci#define CTRL_EI (1<<25) 10362306a36Sopenharmony_ci#define CTRL_ER (1<<24) 10462306a36Sopenharmony_ci#define CTRL_BUS (0xff<<CTRL_BUS_BIT) 10562306a36Sopenharmony_ci#define CTRL_HOSTINT 0xf 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci#define STS_HOST_BIT 31 10862306a36Sopenharmony_ci#define STS_MST_BIT 30 10962306a36Sopenharmony_ci#define STS_TAR_BIT 29 11062306a36Sopenharmony_ci#define STS_DMA_BIT 28 11162306a36Sopenharmony_ci#define STS_DI_BIT 27 11262306a36Sopenharmony_ci#define STS_HI_BIT 26 11362306a36Sopenharmony_ci#define STS_IRQMODE_BIT 24 11462306a36Sopenharmony_ci#define STS_TRACE_BIT 23 11562306a36Sopenharmony_ci#define STS_CFGERRVALID_BIT 20 11662306a36Sopenharmony_ci#define STS_CFGERR_BIT 19 11762306a36Sopenharmony_ci#define STS_INTTYPE_BIT 12 11862306a36Sopenharmony_ci#define STS_INTSTS_BIT 8 11962306a36Sopenharmony_ci#define STS_FDEPTH_BIT 2 12062306a36Sopenharmony_ci#define STS_FNUM_BIT 0 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci#define STS_HOST (1<<STS_HOST_BIT) 12362306a36Sopenharmony_ci#define STS_MST (1<<STS_MST_BIT) 12462306a36Sopenharmony_ci#define STS_TAR (1<<STS_TAR_BIT) 12562306a36Sopenharmony_ci#define STS_DMA (1<<STS_DMA_BIT) 12662306a36Sopenharmony_ci#define STS_DI (1<<STS_DI_BIT) 12762306a36Sopenharmony_ci#define STS_HI (1<<STS_HI_BIT) 12862306a36Sopenharmony_ci#define STS_IRQMODE (0x3<<STS_IRQMODE_BIT) 12962306a36Sopenharmony_ci#define STS_TRACE (1<<STS_TRACE_BIT) 13062306a36Sopenharmony_ci#define STS_CFGERRVALID (1<<STS_CFGERRVALID_BIT) 13162306a36Sopenharmony_ci#define STS_CFGERR (1<<STS_CFGERR_BIT) 13262306a36Sopenharmony_ci#define STS_INTTYPE (0x3f<<STS_INTTYPE_BIT) 13362306a36Sopenharmony_ci#define STS_INTSTS (0xf<<STS_INTSTS_BIT) 13462306a36Sopenharmony_ci#define STS_FDEPTH (0x7<<STS_FDEPTH_BIT) 13562306a36Sopenharmony_ci#define STS_FNUM (0x3<<STS_FNUM_BIT) 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci#define STS_ISYSERR (1<<17) 13862306a36Sopenharmony_ci#define STS_IDMA (1<<16) 13962306a36Sopenharmony_ci#define STS_IDMAERR (1<<15) 14062306a36Sopenharmony_ci#define STS_IMSTABRT (1<<14) 14162306a36Sopenharmony_ci#define STS_ITGTABRT (1<<13) 14262306a36Sopenharmony_ci#define STS_IPARERR (1<<12) 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci#define STS_ERR_IRQ (STS_ISYSERR | STS_IMSTABRT | STS_ITGTABRT | STS_IPARERR) 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistruct grpci2_bd_chan { 14762306a36Sopenharmony_ci unsigned int ctrl; /* 0x00 DMA Control */ 14862306a36Sopenharmony_ci unsigned int nchan; /* 0x04 Next DMA Channel Address */ 14962306a36Sopenharmony_ci unsigned int nbd; /* 0x08 Next Data Descriptor in chan */ 15062306a36Sopenharmony_ci unsigned int res; /* 0x0C Reserved */ 15162306a36Sopenharmony_ci}; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci#define BD_CHAN_EN 0x80000000 15462306a36Sopenharmony_ci#define BD_CHAN_TYPE 0x00300000 15562306a36Sopenharmony_ci#define BD_CHAN_BDCNT 0x0000ffff 15662306a36Sopenharmony_ci#define BD_CHAN_EN_BIT 31 15762306a36Sopenharmony_ci#define BD_CHAN_TYPE_BIT 20 15862306a36Sopenharmony_ci#define BD_CHAN_BDCNT_BIT 0 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistruct grpci2_bd_data { 16162306a36Sopenharmony_ci unsigned int ctrl; /* 0x00 DMA Data Control */ 16262306a36Sopenharmony_ci unsigned int pci_adr; /* 0x04 PCI Start Address */ 16362306a36Sopenharmony_ci unsigned int ahb_adr; /* 0x08 AHB Start address */ 16462306a36Sopenharmony_ci unsigned int next; /* 0x0C Next Data Descriptor in chan */ 16562306a36Sopenharmony_ci}; 16662306a36Sopenharmony_ci 16762306a36Sopenharmony_ci#define BD_DATA_EN 0x80000000 16862306a36Sopenharmony_ci#define BD_DATA_IE 0x40000000 16962306a36Sopenharmony_ci#define BD_DATA_DR 0x20000000 17062306a36Sopenharmony_ci#define BD_DATA_TYPE 0x00300000 17162306a36Sopenharmony_ci#define BD_DATA_ER 0x00080000 17262306a36Sopenharmony_ci#define BD_DATA_LEN 0x0000ffff 17362306a36Sopenharmony_ci#define BD_DATA_EN_BIT 31 17462306a36Sopenharmony_ci#define BD_DATA_IE_BIT 30 17562306a36Sopenharmony_ci#define BD_DATA_DR_BIT 29 17662306a36Sopenharmony_ci#define BD_DATA_TYPE_BIT 20 17762306a36Sopenharmony_ci#define BD_DATA_ER_BIT 19 17862306a36Sopenharmony_ci#define BD_DATA_LEN_BIT 0 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci/* GRPCI2 Capability */ 18162306a36Sopenharmony_cistruct grpci2_cap_first { 18262306a36Sopenharmony_ci unsigned int ctrl; 18362306a36Sopenharmony_ci unsigned int pci2ahb_map[6]; 18462306a36Sopenharmony_ci unsigned int ext2ahb_map; 18562306a36Sopenharmony_ci unsigned int io_map; 18662306a36Sopenharmony_ci unsigned int pcibar_size[6]; 18762306a36Sopenharmony_ci}; 18862306a36Sopenharmony_ci#define CAP9_CTRL_OFS 0 18962306a36Sopenharmony_ci#define CAP9_BAR_OFS 0x4 19062306a36Sopenharmony_ci#define CAP9_IOMAP_OFS 0x20 19162306a36Sopenharmony_ci#define CAP9_BARSIZE_OFS 0x24 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci#define TGT 256 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_cistruct grpci2_priv { 19662306a36Sopenharmony_ci struct leon_pci_info info; /* must be on top of this structure */ 19762306a36Sopenharmony_ci struct grpci2_regs __iomem *regs; 19862306a36Sopenharmony_ci char irq; 19962306a36Sopenharmony_ci char irq_mode; /* IRQ Mode from CAPSTS REG */ 20062306a36Sopenharmony_ci char bt_enabled; 20162306a36Sopenharmony_ci char do_reset; 20262306a36Sopenharmony_ci char irq_mask; 20362306a36Sopenharmony_ci u32 pciid; /* PCI ID of Host */ 20462306a36Sopenharmony_ci unsigned char irq_map[4]; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci /* Virtual IRQ numbers */ 20762306a36Sopenharmony_ci unsigned int virq_err; 20862306a36Sopenharmony_ci unsigned int virq_dma; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci /* AHB PCI Windows */ 21162306a36Sopenharmony_ci unsigned long pci_area; /* MEMORY */ 21262306a36Sopenharmony_ci unsigned long pci_area_end; 21362306a36Sopenharmony_ci unsigned long pci_io; /* I/O */ 21462306a36Sopenharmony_ci unsigned long pci_conf; /* CONFIGURATION */ 21562306a36Sopenharmony_ci unsigned long pci_conf_end; 21662306a36Sopenharmony_ci unsigned long pci_io_va; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci struct grpci2_barcfg tgtbars[6]; 21962306a36Sopenharmony_ci}; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_cistatic DEFINE_SPINLOCK(grpci2_dev_lock); 22262306a36Sopenharmony_cistatic struct grpci2_priv *grpci2priv; 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic int grpci2_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci struct grpci2_priv *priv = dev->bus->sysdata; 22762306a36Sopenharmony_ci int irq_group; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci /* Use default IRQ decoding on PCI BUS0 according slot numbering */ 23062306a36Sopenharmony_ci irq_group = slot & 0x3; 23162306a36Sopenharmony_ci pin = ((pin - 1) + irq_group) & 0x3; 23262306a36Sopenharmony_ci 23362306a36Sopenharmony_ci return priv->irq_map[pin]; 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic int grpci2_cfg_r32(struct grpci2_priv *priv, unsigned int bus, 23762306a36Sopenharmony_ci unsigned int devfn, int where, u32 *val) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci unsigned int *pci_conf; 24062306a36Sopenharmony_ci unsigned long flags; 24162306a36Sopenharmony_ci u32 tmp; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci if (where & 0x3) 24462306a36Sopenharmony_ci return -EINVAL; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci if (bus == 0) { 24762306a36Sopenharmony_ci devfn += (0x8 * 6); /* start at AD16=Device0 */ 24862306a36Sopenharmony_ci } else if (bus == TGT) { 24962306a36Sopenharmony_ci bus = 0; 25062306a36Sopenharmony_ci devfn = 0; /* special case: bridge controller itself */ 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci /* Select bus */ 25462306a36Sopenharmony_ci spin_lock_irqsave(&grpci2_dev_lock, flags); 25562306a36Sopenharmony_ci REGSTORE(priv->regs->ctrl, (REGLOAD(priv->regs->ctrl) & ~(0xff << 16)) | 25662306a36Sopenharmony_ci (bus << 16)); 25762306a36Sopenharmony_ci spin_unlock_irqrestore(&grpci2_dev_lock, flags); 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci /* clear old status */ 26062306a36Sopenharmony_ci REGSTORE(priv->regs->sts_cap, (STS_CFGERR | STS_CFGERRVALID)); 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci pci_conf = (unsigned int *) (priv->pci_conf | 26362306a36Sopenharmony_ci (devfn << 8) | (where & 0xfc)); 26462306a36Sopenharmony_ci tmp = LEON3_BYPASS_LOAD_PA(pci_conf); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci /* Wait until GRPCI2 signals that CFG access is done, it should be 26762306a36Sopenharmony_ci * done instantaneously unless a DMA operation is ongoing... 26862306a36Sopenharmony_ci */ 26962306a36Sopenharmony_ci while ((REGLOAD(priv->regs->sts_cap) & STS_CFGERRVALID) == 0) 27062306a36Sopenharmony_ci ; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci if (REGLOAD(priv->regs->sts_cap) & STS_CFGERR) { 27362306a36Sopenharmony_ci *val = 0xffffffff; 27462306a36Sopenharmony_ci } else { 27562306a36Sopenharmony_ci /* Bus always little endian (unaffected by byte-swapping) */ 27662306a36Sopenharmony_ci *val = swab32(tmp); 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci return 0; 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cistatic int grpci2_cfg_r16(struct grpci2_priv *priv, unsigned int bus, 28362306a36Sopenharmony_ci unsigned int devfn, int where, u32 *val) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci u32 v; 28662306a36Sopenharmony_ci int ret; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci if (where & 0x1) 28962306a36Sopenharmony_ci return -EINVAL; 29062306a36Sopenharmony_ci ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v); 29162306a36Sopenharmony_ci *val = 0xffff & (v >> (8 * (where & 0x3))); 29262306a36Sopenharmony_ci return ret; 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic int grpci2_cfg_r8(struct grpci2_priv *priv, unsigned int bus, 29662306a36Sopenharmony_ci unsigned int devfn, int where, u32 *val) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci u32 v; 29962306a36Sopenharmony_ci int ret; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v); 30262306a36Sopenharmony_ci *val = 0xff & (v >> (8 * (where & 3))); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci return ret; 30562306a36Sopenharmony_ci} 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_cistatic int grpci2_cfg_w32(struct grpci2_priv *priv, unsigned int bus, 30862306a36Sopenharmony_ci unsigned int devfn, int where, u32 val) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci unsigned int *pci_conf; 31162306a36Sopenharmony_ci unsigned long flags; 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci if (where & 0x3) 31462306a36Sopenharmony_ci return -EINVAL; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci if (bus == 0) { 31762306a36Sopenharmony_ci devfn += (0x8 * 6); /* start at AD16=Device0 */ 31862306a36Sopenharmony_ci } else if (bus == TGT) { 31962306a36Sopenharmony_ci bus = 0; 32062306a36Sopenharmony_ci devfn = 0; /* special case: bridge controller itself */ 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci /* Select bus */ 32462306a36Sopenharmony_ci spin_lock_irqsave(&grpci2_dev_lock, flags); 32562306a36Sopenharmony_ci REGSTORE(priv->regs->ctrl, (REGLOAD(priv->regs->ctrl) & ~(0xff << 16)) | 32662306a36Sopenharmony_ci (bus << 16)); 32762306a36Sopenharmony_ci spin_unlock_irqrestore(&grpci2_dev_lock, flags); 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci /* clear old status */ 33062306a36Sopenharmony_ci REGSTORE(priv->regs->sts_cap, (STS_CFGERR | STS_CFGERRVALID)); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci pci_conf = (unsigned int *) (priv->pci_conf | 33362306a36Sopenharmony_ci (devfn << 8) | (where & 0xfc)); 33462306a36Sopenharmony_ci LEON3_BYPASS_STORE_PA(pci_conf, swab32(val)); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci /* Wait until GRPCI2 signals that CFG access is done, it should be 33762306a36Sopenharmony_ci * done instantaneously unless a DMA operation is ongoing... 33862306a36Sopenharmony_ci */ 33962306a36Sopenharmony_ci while ((REGLOAD(priv->regs->sts_cap) & STS_CFGERRVALID) == 0) 34062306a36Sopenharmony_ci ; 34162306a36Sopenharmony_ci 34262306a36Sopenharmony_ci return 0; 34362306a36Sopenharmony_ci} 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_cistatic int grpci2_cfg_w16(struct grpci2_priv *priv, unsigned int bus, 34662306a36Sopenharmony_ci unsigned int devfn, int where, u32 val) 34762306a36Sopenharmony_ci{ 34862306a36Sopenharmony_ci int ret; 34962306a36Sopenharmony_ci u32 v; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci if (where & 0x1) 35262306a36Sopenharmony_ci return -EINVAL; 35362306a36Sopenharmony_ci ret = grpci2_cfg_r32(priv, bus, devfn, where&~3, &v); 35462306a36Sopenharmony_ci if (ret) 35562306a36Sopenharmony_ci return ret; 35662306a36Sopenharmony_ci v = (v & ~(0xffff << (8 * (where & 0x3)))) | 35762306a36Sopenharmony_ci ((0xffff & val) << (8 * (where & 0x3))); 35862306a36Sopenharmony_ci return grpci2_cfg_w32(priv, bus, devfn, where & ~0x3, v); 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistatic int grpci2_cfg_w8(struct grpci2_priv *priv, unsigned int bus, 36262306a36Sopenharmony_ci unsigned int devfn, int where, u32 val) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci int ret; 36562306a36Sopenharmony_ci u32 v; 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci ret = grpci2_cfg_r32(priv, bus, devfn, where & ~0x3, &v); 36862306a36Sopenharmony_ci if (ret != 0) 36962306a36Sopenharmony_ci return ret; 37062306a36Sopenharmony_ci v = (v & ~(0xff << (8 * (where & 0x3)))) | 37162306a36Sopenharmony_ci ((0xff & val) << (8 * (where & 0x3))); 37262306a36Sopenharmony_ci return grpci2_cfg_w32(priv, bus, devfn, where & ~0x3, v); 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci/* Read from Configuration Space. When entering here the PCI layer has taken 37662306a36Sopenharmony_ci * the pci_lock spinlock and IRQ is off. 37762306a36Sopenharmony_ci */ 37862306a36Sopenharmony_cistatic int grpci2_read_config(struct pci_bus *bus, unsigned int devfn, 37962306a36Sopenharmony_ci int where, int size, u32 *val) 38062306a36Sopenharmony_ci{ 38162306a36Sopenharmony_ci struct grpci2_priv *priv = grpci2priv; 38262306a36Sopenharmony_ci unsigned int busno = bus->number; 38362306a36Sopenharmony_ci int ret; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci if (PCI_SLOT(devfn) > 15 || busno > 255) { 38662306a36Sopenharmony_ci *val = ~0; 38762306a36Sopenharmony_ci return 0; 38862306a36Sopenharmony_ci } 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci switch (size) { 39162306a36Sopenharmony_ci case 1: 39262306a36Sopenharmony_ci ret = grpci2_cfg_r8(priv, busno, devfn, where, val); 39362306a36Sopenharmony_ci break; 39462306a36Sopenharmony_ci case 2: 39562306a36Sopenharmony_ci ret = grpci2_cfg_r16(priv, busno, devfn, where, val); 39662306a36Sopenharmony_ci break; 39762306a36Sopenharmony_ci case 4: 39862306a36Sopenharmony_ci ret = grpci2_cfg_r32(priv, busno, devfn, where, val); 39962306a36Sopenharmony_ci break; 40062306a36Sopenharmony_ci default: 40162306a36Sopenharmony_ci ret = -EINVAL; 40262306a36Sopenharmony_ci break; 40362306a36Sopenharmony_ci } 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci#ifdef GRPCI2_DEBUG_CFGACCESS 40662306a36Sopenharmony_ci printk(KERN_INFO "grpci2_read_config: [%02x:%02x:%x] ofs=%d val=%x " 40762306a36Sopenharmony_ci "size=%d\n", busno, PCI_SLOT(devfn), PCI_FUNC(devfn), where, 40862306a36Sopenharmony_ci *val, size); 40962306a36Sopenharmony_ci#endif 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci return ret; 41262306a36Sopenharmony_ci} 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci/* Write to Configuration Space. When entering here the PCI layer has taken 41562306a36Sopenharmony_ci * the pci_lock spinlock and IRQ is off. 41662306a36Sopenharmony_ci */ 41762306a36Sopenharmony_cistatic int grpci2_write_config(struct pci_bus *bus, unsigned int devfn, 41862306a36Sopenharmony_ci int where, int size, u32 val) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci struct grpci2_priv *priv = grpci2priv; 42162306a36Sopenharmony_ci unsigned int busno = bus->number; 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci if (PCI_SLOT(devfn) > 15 || busno > 255) 42462306a36Sopenharmony_ci return 0; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci#ifdef GRPCI2_DEBUG_CFGACCESS 42762306a36Sopenharmony_ci printk(KERN_INFO "grpci2_write_config: [%02x:%02x:%x] ofs=%d size=%d " 42862306a36Sopenharmony_ci "val=%x\n", busno, PCI_SLOT(devfn), PCI_FUNC(devfn), 42962306a36Sopenharmony_ci where, size, val); 43062306a36Sopenharmony_ci#endif 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci switch (size) { 43362306a36Sopenharmony_ci default: 43462306a36Sopenharmony_ci return -EINVAL; 43562306a36Sopenharmony_ci case 1: 43662306a36Sopenharmony_ci return grpci2_cfg_w8(priv, busno, devfn, where, val); 43762306a36Sopenharmony_ci case 2: 43862306a36Sopenharmony_ci return grpci2_cfg_w16(priv, busno, devfn, where, val); 43962306a36Sopenharmony_ci case 4: 44062306a36Sopenharmony_ci return grpci2_cfg_w32(priv, busno, devfn, where, val); 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci} 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_cistatic struct pci_ops grpci2_ops = { 44562306a36Sopenharmony_ci .read = grpci2_read_config, 44662306a36Sopenharmony_ci .write = grpci2_write_config, 44762306a36Sopenharmony_ci}; 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci/* GENIRQ IRQ chip implementation for GRPCI2 irqmode=0..2. In configuration 45062306a36Sopenharmony_ci * 3 where all PCI Interrupts has a separate IRQ on the system IRQ controller 45162306a36Sopenharmony_ci * this is not needed and the standard IRQ controller can be used. 45262306a36Sopenharmony_ci */ 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cistatic void grpci2_mask_irq(struct irq_data *data) 45562306a36Sopenharmony_ci{ 45662306a36Sopenharmony_ci unsigned long flags; 45762306a36Sopenharmony_ci unsigned int irqidx; 45862306a36Sopenharmony_ci struct grpci2_priv *priv = grpci2priv; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci irqidx = (unsigned int)data->chip_data - 1; 46162306a36Sopenharmony_ci if (irqidx > 3) /* only mask PCI interrupts here */ 46262306a36Sopenharmony_ci return; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci spin_lock_irqsave(&grpci2_dev_lock, flags); 46562306a36Sopenharmony_ci REGSTORE(priv->regs->ctrl, REGLOAD(priv->regs->ctrl) & ~(1 << irqidx)); 46662306a36Sopenharmony_ci spin_unlock_irqrestore(&grpci2_dev_lock, flags); 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_cistatic void grpci2_unmask_irq(struct irq_data *data) 47062306a36Sopenharmony_ci{ 47162306a36Sopenharmony_ci unsigned long flags; 47262306a36Sopenharmony_ci unsigned int irqidx; 47362306a36Sopenharmony_ci struct grpci2_priv *priv = grpci2priv; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci irqidx = (unsigned int)data->chip_data - 1; 47662306a36Sopenharmony_ci if (irqidx > 3) /* only unmask PCI interrupts here */ 47762306a36Sopenharmony_ci return; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ci spin_lock_irqsave(&grpci2_dev_lock, flags); 48062306a36Sopenharmony_ci REGSTORE(priv->regs->ctrl, REGLOAD(priv->regs->ctrl) | (1 << irqidx)); 48162306a36Sopenharmony_ci spin_unlock_irqrestore(&grpci2_dev_lock, flags); 48262306a36Sopenharmony_ci} 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_cistatic unsigned int grpci2_startup_irq(struct irq_data *data) 48562306a36Sopenharmony_ci{ 48662306a36Sopenharmony_ci grpci2_unmask_irq(data); 48762306a36Sopenharmony_ci return 0; 48862306a36Sopenharmony_ci} 48962306a36Sopenharmony_ci 49062306a36Sopenharmony_cistatic void grpci2_shutdown_irq(struct irq_data *data) 49162306a36Sopenharmony_ci{ 49262306a36Sopenharmony_ci grpci2_mask_irq(data); 49362306a36Sopenharmony_ci} 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_cistatic struct irq_chip grpci2_irq = { 49662306a36Sopenharmony_ci .name = "grpci2", 49762306a36Sopenharmony_ci .irq_startup = grpci2_startup_irq, 49862306a36Sopenharmony_ci .irq_shutdown = grpci2_shutdown_irq, 49962306a36Sopenharmony_ci .irq_mask = grpci2_mask_irq, 50062306a36Sopenharmony_ci .irq_unmask = grpci2_unmask_irq, 50162306a36Sopenharmony_ci}; 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci/* Handle one or multiple IRQs from the PCI core */ 50462306a36Sopenharmony_cistatic void grpci2_pci_flow_irq(struct irq_desc *desc) 50562306a36Sopenharmony_ci{ 50662306a36Sopenharmony_ci struct grpci2_priv *priv = grpci2priv; 50762306a36Sopenharmony_ci int i, ack = 0; 50862306a36Sopenharmony_ci unsigned int ctrl, sts_cap, pci_ints; 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_ci ctrl = REGLOAD(priv->regs->ctrl); 51162306a36Sopenharmony_ci sts_cap = REGLOAD(priv->regs->sts_cap); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci /* Error Interrupt? */ 51462306a36Sopenharmony_ci if (sts_cap & STS_ERR_IRQ) { 51562306a36Sopenharmony_ci generic_handle_irq(priv->virq_err); 51662306a36Sopenharmony_ci ack = 1; 51762306a36Sopenharmony_ci } 51862306a36Sopenharmony_ci 51962306a36Sopenharmony_ci /* PCI Interrupt? */ 52062306a36Sopenharmony_ci pci_ints = ((~sts_cap) >> STS_INTSTS_BIT) & ctrl & CTRL_HOSTINT; 52162306a36Sopenharmony_ci if (pci_ints) { 52262306a36Sopenharmony_ci /* Call respective PCI Interrupt handler */ 52362306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 52462306a36Sopenharmony_ci if (pci_ints & (1 << i)) 52562306a36Sopenharmony_ci generic_handle_irq(priv->irq_map[i]); 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci ack = 1; 52862306a36Sopenharmony_ci } 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci /* 53162306a36Sopenharmony_ci * Decode DMA Interrupt only when shared with Err and PCI INTX#, when 53262306a36Sopenharmony_ci * the DMA is a unique IRQ the DMA interrupts doesn't end up here, they 53362306a36Sopenharmony_ci * goes directly to DMA ISR. 53462306a36Sopenharmony_ci */ 53562306a36Sopenharmony_ci if ((priv->irq_mode == 0) && (sts_cap & (STS_IDMA | STS_IDMAERR))) { 53662306a36Sopenharmony_ci generic_handle_irq(priv->virq_dma); 53762306a36Sopenharmony_ci ack = 1; 53862306a36Sopenharmony_ci } 53962306a36Sopenharmony_ci 54062306a36Sopenharmony_ci /* 54162306a36Sopenharmony_ci * Call "first level" IRQ chip end-of-irq handler. It will ACK LEON IRQ 54262306a36Sopenharmony_ci * Controller, this must be done after IRQ sources have been handled to 54362306a36Sopenharmony_ci * avoid double IRQ generation 54462306a36Sopenharmony_ci */ 54562306a36Sopenharmony_ci if (ack) 54662306a36Sopenharmony_ci desc->irq_data.chip->irq_eoi(&desc->irq_data); 54762306a36Sopenharmony_ci} 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ci/* Create a virtual IRQ */ 55062306a36Sopenharmony_cistatic unsigned int grpci2_build_device_irq(unsigned int irq) 55162306a36Sopenharmony_ci{ 55262306a36Sopenharmony_ci unsigned int virq = 0, pil; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_ci pil = 1 << 8; 55562306a36Sopenharmony_ci virq = irq_alloc(irq, pil); 55662306a36Sopenharmony_ci if (virq == 0) 55762306a36Sopenharmony_ci goto out; 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci irq_set_chip_and_handler_name(virq, &grpci2_irq, handle_simple_irq, 56062306a36Sopenharmony_ci "pcilvl"); 56162306a36Sopenharmony_ci irq_set_chip_data(virq, (void *)irq); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ciout: 56462306a36Sopenharmony_ci return virq; 56562306a36Sopenharmony_ci} 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_cistatic void grpci2_hw_init(struct grpci2_priv *priv) 56862306a36Sopenharmony_ci{ 56962306a36Sopenharmony_ci u32 ahbadr, pciadr, bar_sz, capptr, io_map, data; 57062306a36Sopenharmony_ci struct grpci2_regs __iomem *regs = priv->regs; 57162306a36Sopenharmony_ci int i; 57262306a36Sopenharmony_ci struct grpci2_barcfg *barcfg = priv->tgtbars; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci /* Reset any earlier setup */ 57562306a36Sopenharmony_ci if (priv->do_reset) { 57662306a36Sopenharmony_ci printk(KERN_INFO "GRPCI2: Resetting PCI bus\n"); 57762306a36Sopenharmony_ci REGSTORE(regs->ctrl, CTRL_RESET); 57862306a36Sopenharmony_ci ssleep(1); /* Wait for boards to settle */ 57962306a36Sopenharmony_ci } 58062306a36Sopenharmony_ci REGSTORE(regs->ctrl, 0); 58162306a36Sopenharmony_ci REGSTORE(regs->sts_cap, ~0); /* Clear Status */ 58262306a36Sopenharmony_ci REGSTORE(regs->dma_ctrl, 0); 58362306a36Sopenharmony_ci REGSTORE(regs->dma_bdbase, 0); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci /* Translate I/O accesses to 0, I/O Space always @ PCI low 64Kbytes */ 58662306a36Sopenharmony_ci REGSTORE(regs->io_map, REGLOAD(regs->io_map) & 0x0000ffff); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci /* set 1:1 mapping between AHB -> PCI memory space, for all Masters 58962306a36Sopenharmony_ci * Each AHB master has it's own mapping registers. Max 16 AHB masters. 59062306a36Sopenharmony_ci */ 59162306a36Sopenharmony_ci for (i = 0; i < 16; i++) 59262306a36Sopenharmony_ci REGSTORE(regs->ahbmst_map[i], priv->pci_area); 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci /* Get the GRPCI2 Host PCI ID */ 59562306a36Sopenharmony_ci grpci2_cfg_r32(priv, TGT, 0, PCI_VENDOR_ID, &priv->pciid); 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci /* Get address to first (always defined) capability structure */ 59862306a36Sopenharmony_ci grpci2_cfg_r8(priv, TGT, 0, PCI_CAPABILITY_LIST, &capptr); 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci /* Enable/Disable Byte twisting */ 60162306a36Sopenharmony_ci grpci2_cfg_r32(priv, TGT, 0, capptr+CAP9_IOMAP_OFS, &io_map); 60262306a36Sopenharmony_ci io_map = (io_map & ~0x1) | (priv->bt_enabled ? 1 : 0); 60362306a36Sopenharmony_ci grpci2_cfg_w32(priv, TGT, 0, capptr+CAP9_IOMAP_OFS, io_map); 60462306a36Sopenharmony_ci 60562306a36Sopenharmony_ci /* Setup the Host's PCI Target BARs for other peripherals to access, 60662306a36Sopenharmony_ci * and do DMA to the host's memory. The target BARs can be sized and 60762306a36Sopenharmony_ci * enabled individually. 60862306a36Sopenharmony_ci * 60962306a36Sopenharmony_ci * User may set custom target BARs, but default is: 61062306a36Sopenharmony_ci * The first BARs is used to map kernel low (DMA is part of normal 61162306a36Sopenharmony_ci * region on sparc which is SRMMU_MAXMEM big) main memory 1:1 to the 61262306a36Sopenharmony_ci * PCI bus, the other BARs are disabled. We assume that the first BAR 61362306a36Sopenharmony_ci * is always available. 61462306a36Sopenharmony_ci */ 61562306a36Sopenharmony_ci for (i = 0; i < 6; i++) { 61662306a36Sopenharmony_ci if (barcfg[i].pciadr != ~0 && barcfg[i].ahbadr != ~0) { 61762306a36Sopenharmony_ci /* Target BARs must have the proper alignment */ 61862306a36Sopenharmony_ci ahbadr = barcfg[i].ahbadr; 61962306a36Sopenharmony_ci pciadr = barcfg[i].pciadr; 62062306a36Sopenharmony_ci bar_sz = ((pciadr - 1) & ~pciadr) + 1; 62162306a36Sopenharmony_ci } else { 62262306a36Sopenharmony_ci if (i == 0) { 62362306a36Sopenharmony_ci /* Map main memory */ 62462306a36Sopenharmony_ci bar_sz = 0xf0000008; /* 256MB prefetchable */ 62562306a36Sopenharmony_ci ahbadr = 0xf0000000 & (u32)__pa(PAGE_ALIGN( 62662306a36Sopenharmony_ci (unsigned long) &_end)); 62762306a36Sopenharmony_ci pciadr = ahbadr; 62862306a36Sopenharmony_ci } else { 62962306a36Sopenharmony_ci bar_sz = 0; 63062306a36Sopenharmony_ci ahbadr = 0; 63162306a36Sopenharmony_ci pciadr = 0; 63262306a36Sopenharmony_ci } 63362306a36Sopenharmony_ci } 63462306a36Sopenharmony_ci grpci2_cfg_w32(priv, TGT, 0, capptr+CAP9_BARSIZE_OFS+i*4, 63562306a36Sopenharmony_ci bar_sz); 63662306a36Sopenharmony_ci grpci2_cfg_w32(priv, TGT, 0, PCI_BASE_ADDRESS_0+i*4, pciadr); 63762306a36Sopenharmony_ci grpci2_cfg_w32(priv, TGT, 0, capptr+CAP9_BAR_OFS+i*4, ahbadr); 63862306a36Sopenharmony_ci printk(KERN_INFO " TGT BAR[%d]: 0x%08x (PCI)-> 0x%08x\n", 63962306a36Sopenharmony_ci i, pciadr, ahbadr); 64062306a36Sopenharmony_ci } 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci /* set as bus master and enable pci memory responses */ 64362306a36Sopenharmony_ci grpci2_cfg_r32(priv, TGT, 0, PCI_COMMAND, &data); 64462306a36Sopenharmony_ci data |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); 64562306a36Sopenharmony_ci grpci2_cfg_w32(priv, TGT, 0, PCI_COMMAND, data); 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci /* Enable Error respone (CPU-TRAP) on illegal memory access. */ 64862306a36Sopenharmony_ci REGSTORE(regs->ctrl, CTRL_ER | CTRL_PE); 64962306a36Sopenharmony_ci} 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_cistatic irqreturn_t grpci2_jump_interrupt(int irq, void *arg) 65262306a36Sopenharmony_ci{ 65362306a36Sopenharmony_ci printk(KERN_ERR "GRPCI2: Jump IRQ happened\n"); 65462306a36Sopenharmony_ci return IRQ_NONE; 65562306a36Sopenharmony_ci} 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci/* Handle GRPCI2 Error Interrupt */ 65862306a36Sopenharmony_cistatic irqreturn_t grpci2_err_interrupt(int irq, void *arg) 65962306a36Sopenharmony_ci{ 66062306a36Sopenharmony_ci struct grpci2_priv *priv = arg; 66162306a36Sopenharmony_ci struct grpci2_regs __iomem *regs = priv->regs; 66262306a36Sopenharmony_ci unsigned int status; 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci status = REGLOAD(regs->sts_cap); 66562306a36Sopenharmony_ci if ((status & STS_ERR_IRQ) == 0) 66662306a36Sopenharmony_ci return IRQ_NONE; 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci if (status & STS_IPARERR) 66962306a36Sopenharmony_ci printk(KERN_ERR "GRPCI2: Parity Error\n"); 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci if (status & STS_ITGTABRT) 67262306a36Sopenharmony_ci printk(KERN_ERR "GRPCI2: Target Abort\n"); 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci if (status & STS_IMSTABRT) 67562306a36Sopenharmony_ci printk(KERN_ERR "GRPCI2: Master Abort\n"); 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci if (status & STS_ISYSERR) 67862306a36Sopenharmony_ci printk(KERN_ERR "GRPCI2: System Error\n"); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci /* Clear handled INT TYPE IRQs */ 68162306a36Sopenharmony_ci REGSTORE(regs->sts_cap, status & STS_ERR_IRQ); 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci return IRQ_HANDLED; 68462306a36Sopenharmony_ci} 68562306a36Sopenharmony_ci 68662306a36Sopenharmony_cistatic int grpci2_of_probe(struct platform_device *ofdev) 68762306a36Sopenharmony_ci{ 68862306a36Sopenharmony_ci struct grpci2_regs __iomem *regs; 68962306a36Sopenharmony_ci struct grpci2_priv *priv; 69062306a36Sopenharmony_ci int err, i, len; 69162306a36Sopenharmony_ci const int *tmp; 69262306a36Sopenharmony_ci unsigned int capability; 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci if (grpci2priv) { 69562306a36Sopenharmony_ci printk(KERN_ERR "GRPCI2: only one GRPCI2 core supported\n"); 69662306a36Sopenharmony_ci return -ENODEV; 69762306a36Sopenharmony_ci } 69862306a36Sopenharmony_ci 69962306a36Sopenharmony_ci if (ofdev->num_resources < 3) { 70062306a36Sopenharmony_ci printk(KERN_ERR "GRPCI2: not enough APB/AHB resources\n"); 70162306a36Sopenharmony_ci return -EIO; 70262306a36Sopenharmony_ci } 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci /* Find Device Address */ 70562306a36Sopenharmony_ci regs = of_ioremap(&ofdev->resource[0], 0, 70662306a36Sopenharmony_ci resource_size(&ofdev->resource[0]), 70762306a36Sopenharmony_ci "grlib-grpci2 regs"); 70862306a36Sopenharmony_ci if (regs == NULL) { 70962306a36Sopenharmony_ci printk(KERN_ERR "GRPCI2: ioremap failed\n"); 71062306a36Sopenharmony_ci return -EIO; 71162306a36Sopenharmony_ci } 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci /* 71462306a36Sopenharmony_ci * Check that we're in Host Slot and that we can act as a Host Bridge 71562306a36Sopenharmony_ci * and not only as target. 71662306a36Sopenharmony_ci */ 71762306a36Sopenharmony_ci capability = REGLOAD(regs->sts_cap); 71862306a36Sopenharmony_ci if ((capability & STS_HOST) || !(capability & STS_MST)) { 71962306a36Sopenharmony_ci printk(KERN_INFO "GRPCI2: not in host system slot\n"); 72062306a36Sopenharmony_ci err = -EIO; 72162306a36Sopenharmony_ci goto err1; 72262306a36Sopenharmony_ci } 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci priv = grpci2priv = kzalloc(sizeof(struct grpci2_priv), GFP_KERNEL); 72562306a36Sopenharmony_ci if (grpci2priv == NULL) { 72662306a36Sopenharmony_ci err = -ENOMEM; 72762306a36Sopenharmony_ci goto err1; 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci priv->regs = regs; 73062306a36Sopenharmony_ci priv->irq = ofdev->archdata.irqs[0]; /* BASE IRQ */ 73162306a36Sopenharmony_ci priv->irq_mode = (capability & STS_IRQMODE) >> STS_IRQMODE_BIT; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci printk(KERN_INFO "GRPCI2: host found at %p, irq%d\n", regs, priv->irq); 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci /* Byte twisting should be made configurable from kernel command line */ 73662306a36Sopenharmony_ci priv->bt_enabled = 1; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci /* Let user do custom Target BAR assignment */ 73962306a36Sopenharmony_ci tmp = of_get_property(ofdev->dev.of_node, "barcfg", &len); 74062306a36Sopenharmony_ci if (tmp && (len == 2*4*6)) 74162306a36Sopenharmony_ci memcpy(priv->tgtbars, tmp, 2*4*6); 74262306a36Sopenharmony_ci else 74362306a36Sopenharmony_ci memset(priv->tgtbars, -1, 2*4*6); 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci /* Limit IRQ unmasking in irq_mode 2 and 3 */ 74662306a36Sopenharmony_ci tmp = of_get_property(ofdev->dev.of_node, "irq_mask", &len); 74762306a36Sopenharmony_ci if (tmp && (len == 4)) 74862306a36Sopenharmony_ci priv->do_reset = *tmp; 74962306a36Sopenharmony_ci else 75062306a36Sopenharmony_ci priv->irq_mask = 0xf; 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci /* Optional PCI reset. Force PCI reset on startup */ 75362306a36Sopenharmony_ci tmp = of_get_property(ofdev->dev.of_node, "reset", &len); 75462306a36Sopenharmony_ci if (tmp && (len == 4)) 75562306a36Sopenharmony_ci priv->do_reset = *tmp; 75662306a36Sopenharmony_ci else 75762306a36Sopenharmony_ci priv->do_reset = 0; 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci /* Find PCI Memory, I/O and Configuration Space Windows */ 76062306a36Sopenharmony_ci priv->pci_area = ofdev->resource[1].start; 76162306a36Sopenharmony_ci priv->pci_area_end = ofdev->resource[1].end+1; 76262306a36Sopenharmony_ci priv->pci_io = ofdev->resource[2].start; 76362306a36Sopenharmony_ci priv->pci_conf = ofdev->resource[2].start + 0x10000; 76462306a36Sopenharmony_ci priv->pci_conf_end = priv->pci_conf + 0x10000; 76562306a36Sopenharmony_ci priv->pci_io_va = (unsigned long)ioremap(priv->pci_io, 0x10000); 76662306a36Sopenharmony_ci if (!priv->pci_io_va) { 76762306a36Sopenharmony_ci err = -EIO; 76862306a36Sopenharmony_ci goto err2; 76962306a36Sopenharmony_ci } 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci printk(KERN_INFO 77262306a36Sopenharmony_ci "GRPCI2: MEMORY SPACE [0x%08lx - 0x%08lx]\n" 77362306a36Sopenharmony_ci " I/O SPACE [0x%08lx - 0x%08lx]\n" 77462306a36Sopenharmony_ci " CONFIG SPACE [0x%08lx - 0x%08lx]\n", 77562306a36Sopenharmony_ci priv->pci_area, priv->pci_area_end-1, 77662306a36Sopenharmony_ci priv->pci_io, priv->pci_conf-1, 77762306a36Sopenharmony_ci priv->pci_conf, priv->pci_conf_end-1); 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_ci /* 78062306a36Sopenharmony_ci * I/O Space resources in I/O Window mapped into Virtual Adr Space 78162306a36Sopenharmony_ci * We never use low 4KB because some devices seem have problems using 78262306a36Sopenharmony_ci * address 0. 78362306a36Sopenharmony_ci */ 78462306a36Sopenharmony_ci memset(&priv->info.io_space, 0, sizeof(struct resource)); 78562306a36Sopenharmony_ci priv->info.io_space.name = "GRPCI2 PCI I/O Space"; 78662306a36Sopenharmony_ci priv->info.io_space.start = priv->pci_io_va + 0x1000; 78762306a36Sopenharmony_ci priv->info.io_space.end = priv->pci_io_va + 0x10000 - 1; 78862306a36Sopenharmony_ci priv->info.io_space.flags = IORESOURCE_IO; 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci /* 79162306a36Sopenharmony_ci * GRPCI2 has no prefetchable memory, map everything as 79262306a36Sopenharmony_ci * non-prefetchable memory 79362306a36Sopenharmony_ci */ 79462306a36Sopenharmony_ci memset(&priv->info.mem_space, 0, sizeof(struct resource)); 79562306a36Sopenharmony_ci priv->info.mem_space.name = "GRPCI2 PCI MEM Space"; 79662306a36Sopenharmony_ci priv->info.mem_space.start = priv->pci_area; 79762306a36Sopenharmony_ci priv->info.mem_space.end = priv->pci_area_end - 1; 79862306a36Sopenharmony_ci priv->info.mem_space.flags = IORESOURCE_MEM; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci if (request_resource(&iomem_resource, &priv->info.mem_space) < 0) 80162306a36Sopenharmony_ci goto err3; 80262306a36Sopenharmony_ci if (request_resource(&ioport_resource, &priv->info.io_space) < 0) 80362306a36Sopenharmony_ci goto err4; 80462306a36Sopenharmony_ci 80562306a36Sopenharmony_ci /* setup maximum supported PCI buses */ 80662306a36Sopenharmony_ci priv->info.busn.name = "GRPCI2 busn"; 80762306a36Sopenharmony_ci priv->info.busn.start = 0; 80862306a36Sopenharmony_ci priv->info.busn.end = 255; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci grpci2_hw_init(priv); 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci /* 81362306a36Sopenharmony_ci * Get PCI Interrupt to System IRQ mapping and setup IRQ handling 81462306a36Sopenharmony_ci * Error IRQ always on PCI INTA. 81562306a36Sopenharmony_ci */ 81662306a36Sopenharmony_ci if (priv->irq_mode < 2) { 81762306a36Sopenharmony_ci /* All PCI interrupts are shared using the same system IRQ */ 81862306a36Sopenharmony_ci leon_update_virq_handling(priv->irq, grpci2_pci_flow_irq, 81962306a36Sopenharmony_ci "pcilvl", 0); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci priv->irq_map[0] = grpci2_build_device_irq(1); 82262306a36Sopenharmony_ci priv->irq_map[1] = grpci2_build_device_irq(2); 82362306a36Sopenharmony_ci priv->irq_map[2] = grpci2_build_device_irq(3); 82462306a36Sopenharmony_ci priv->irq_map[3] = grpci2_build_device_irq(4); 82562306a36Sopenharmony_ci 82662306a36Sopenharmony_ci priv->virq_err = grpci2_build_device_irq(5); 82762306a36Sopenharmony_ci if (priv->irq_mode & 1) 82862306a36Sopenharmony_ci priv->virq_dma = ofdev->archdata.irqs[1]; 82962306a36Sopenharmony_ci else 83062306a36Sopenharmony_ci priv->virq_dma = grpci2_build_device_irq(6); 83162306a36Sopenharmony_ci 83262306a36Sopenharmony_ci /* Enable IRQs on LEON IRQ controller */ 83362306a36Sopenharmony_ci err = request_irq(priv->irq, grpci2_jump_interrupt, 0, 83462306a36Sopenharmony_ci "GRPCI2_JUMP", priv); 83562306a36Sopenharmony_ci if (err) 83662306a36Sopenharmony_ci printk(KERN_ERR "GRPCI2: ERR IRQ request failed\n"); 83762306a36Sopenharmony_ci } else { 83862306a36Sopenharmony_ci /* All PCI interrupts have an unique IRQ interrupt */ 83962306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 84062306a36Sopenharmony_ci /* Make LEON IRQ layer handle level IRQ by acking */ 84162306a36Sopenharmony_ci leon_update_virq_handling(ofdev->archdata.irqs[i], 84262306a36Sopenharmony_ci handle_fasteoi_irq, "pcilvl", 84362306a36Sopenharmony_ci 1); 84462306a36Sopenharmony_ci priv->irq_map[i] = ofdev->archdata.irqs[i]; 84562306a36Sopenharmony_ci } 84662306a36Sopenharmony_ci priv->virq_err = priv->irq_map[0]; 84762306a36Sopenharmony_ci if (priv->irq_mode & 1) 84862306a36Sopenharmony_ci priv->virq_dma = ofdev->archdata.irqs[4]; 84962306a36Sopenharmony_ci else 85062306a36Sopenharmony_ci priv->virq_dma = priv->irq_map[0]; 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci /* Unmask all PCI interrupts, request_irq will not do that */ 85362306a36Sopenharmony_ci REGSTORE(regs->ctrl, REGLOAD(regs->ctrl)|(priv->irq_mask&0xf)); 85462306a36Sopenharmony_ci } 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci /* Setup IRQ handler for non-configuration space access errors */ 85762306a36Sopenharmony_ci err = request_irq(priv->virq_err, grpci2_err_interrupt, IRQF_SHARED, 85862306a36Sopenharmony_ci "GRPCI2_ERR", priv); 85962306a36Sopenharmony_ci if (err) { 86062306a36Sopenharmony_ci printk(KERN_DEBUG "GRPCI2: ERR VIRQ request failed: %d\n", err); 86162306a36Sopenharmony_ci goto err5; 86262306a36Sopenharmony_ci } 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci /* 86562306a36Sopenharmony_ci * Enable Error Interrupts. PCI interrupts are unmasked once request_irq 86662306a36Sopenharmony_ci * is called by the PCI Device drivers 86762306a36Sopenharmony_ci */ 86862306a36Sopenharmony_ci REGSTORE(regs->ctrl, REGLOAD(regs->ctrl) | CTRL_EI | CTRL_SI); 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci /* Init common layer and scan buses */ 87162306a36Sopenharmony_ci priv->info.ops = &grpci2_ops; 87262306a36Sopenharmony_ci priv->info.map_irq = grpci2_map_irq; 87362306a36Sopenharmony_ci leon_pci_init(ofdev, &priv->info); 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci return 0; 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_cierr5: 87862306a36Sopenharmony_ci release_resource(&priv->info.io_space); 87962306a36Sopenharmony_cierr4: 88062306a36Sopenharmony_ci release_resource(&priv->info.mem_space); 88162306a36Sopenharmony_cierr3: 88262306a36Sopenharmony_ci err = -ENOMEM; 88362306a36Sopenharmony_ci iounmap((void __iomem *)priv->pci_io_va); 88462306a36Sopenharmony_cierr2: 88562306a36Sopenharmony_ci kfree(priv); 88662306a36Sopenharmony_cierr1: 88762306a36Sopenharmony_ci of_iounmap(&ofdev->resource[0], regs, 88862306a36Sopenharmony_ci resource_size(&ofdev->resource[0])); 88962306a36Sopenharmony_ci return err; 89062306a36Sopenharmony_ci} 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_cistatic const struct of_device_id grpci2_of_match[] = { 89362306a36Sopenharmony_ci { 89462306a36Sopenharmony_ci .name = "GAISLER_GRPCI2", 89562306a36Sopenharmony_ci }, 89662306a36Sopenharmony_ci { 89762306a36Sopenharmony_ci .name = "01_07c", 89862306a36Sopenharmony_ci }, 89962306a36Sopenharmony_ci {}, 90062306a36Sopenharmony_ci}; 90162306a36Sopenharmony_ci 90262306a36Sopenharmony_cistatic struct platform_driver grpci2_of_driver = { 90362306a36Sopenharmony_ci .driver = { 90462306a36Sopenharmony_ci .name = "grpci2", 90562306a36Sopenharmony_ci .of_match_table = grpci2_of_match, 90662306a36Sopenharmony_ci }, 90762306a36Sopenharmony_ci .probe = grpci2_of_probe, 90862306a36Sopenharmony_ci}; 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_cistatic int __init grpci2_init(void) 91162306a36Sopenharmony_ci{ 91262306a36Sopenharmony_ci return platform_driver_register(&grpci2_of_driver); 91362306a36Sopenharmony_ci} 91462306a36Sopenharmony_ci 91562306a36Sopenharmony_cisubsys_initcall(grpci2_init); 916