1*a88b5ba8SSam Ravnborg /* pci_fire.c: Sun4u platform PCI-E controller support. 2*a88b5ba8SSam Ravnborg * 3*a88b5ba8SSam Ravnborg * Copyright (C) 2007 David S. Miller (davem@davemloft.net) 4*a88b5ba8SSam Ravnborg */ 5*a88b5ba8SSam Ravnborg #include <linux/kernel.h> 6*a88b5ba8SSam Ravnborg #include <linux/pci.h> 7*a88b5ba8SSam Ravnborg #include <linux/slab.h> 8*a88b5ba8SSam Ravnborg #include <linux/init.h> 9*a88b5ba8SSam Ravnborg #include <linux/msi.h> 10*a88b5ba8SSam Ravnborg #include <linux/irq.h> 11*a88b5ba8SSam Ravnborg #include <linux/of_device.h> 12*a88b5ba8SSam Ravnborg 13*a88b5ba8SSam Ravnborg #include <asm/prom.h> 14*a88b5ba8SSam Ravnborg #include <asm/irq.h> 15*a88b5ba8SSam Ravnborg #include <asm/upa.h> 16*a88b5ba8SSam Ravnborg 17*a88b5ba8SSam Ravnborg #include "pci_impl.h" 18*a88b5ba8SSam Ravnborg 19*a88b5ba8SSam Ravnborg #define DRIVER_NAME "fire" 20*a88b5ba8SSam Ravnborg #define PFX DRIVER_NAME ": " 21*a88b5ba8SSam Ravnborg 22*a88b5ba8SSam Ravnborg #define FIRE_IOMMU_CONTROL 0x40000UL 23*a88b5ba8SSam Ravnborg #define FIRE_IOMMU_TSBBASE 0x40008UL 24*a88b5ba8SSam Ravnborg #define FIRE_IOMMU_FLUSH 0x40100UL 25*a88b5ba8SSam Ravnborg #define FIRE_IOMMU_FLUSHINV 0x40108UL 26*a88b5ba8SSam Ravnborg 27*a88b5ba8SSam Ravnborg static int pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm) 28*a88b5ba8SSam Ravnborg { 29*a88b5ba8SSam Ravnborg struct iommu *iommu = pbm->iommu; 30*a88b5ba8SSam Ravnborg u32 vdma[2], dma_mask; 31*a88b5ba8SSam Ravnborg u64 control; 32*a88b5ba8SSam Ravnborg int tsbsize, err; 33*a88b5ba8SSam Ravnborg 34*a88b5ba8SSam Ravnborg /* No virtual-dma property on these guys, use largest size. */ 35*a88b5ba8SSam Ravnborg vdma[0] = 0xc0000000; /* base */ 36*a88b5ba8SSam Ravnborg vdma[1] = 0x40000000; /* size */ 37*a88b5ba8SSam Ravnborg dma_mask = 0xffffffff; 38*a88b5ba8SSam Ravnborg tsbsize = 128; 39*a88b5ba8SSam Ravnborg 40*a88b5ba8SSam Ravnborg /* Register addresses. */ 41*a88b5ba8SSam Ravnborg iommu->iommu_control = pbm->pbm_regs + FIRE_IOMMU_CONTROL; 42*a88b5ba8SSam Ravnborg iommu->iommu_tsbbase = pbm->pbm_regs + FIRE_IOMMU_TSBBASE; 43*a88b5ba8SSam Ravnborg iommu->iommu_flush = pbm->pbm_regs + FIRE_IOMMU_FLUSH; 44*a88b5ba8SSam Ravnborg iommu->iommu_flushinv = pbm->pbm_regs + FIRE_IOMMU_FLUSHINV; 45*a88b5ba8SSam Ravnborg 46*a88b5ba8SSam Ravnborg /* We use the main control/status register of FIRE as the write 47*a88b5ba8SSam Ravnborg * completion register. 48*a88b5ba8SSam Ravnborg */ 49*a88b5ba8SSam Ravnborg iommu->write_complete_reg = pbm->controller_regs + 0x410000UL; 50*a88b5ba8SSam Ravnborg 51*a88b5ba8SSam Ravnborg /* 52*a88b5ba8SSam Ravnborg * Invalidate TLB Entries. 53*a88b5ba8SSam Ravnborg */ 54*a88b5ba8SSam Ravnborg upa_writeq(~(u64)0, iommu->iommu_flushinv); 55*a88b5ba8SSam Ravnborg 56*a88b5ba8SSam Ravnborg err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, 57*a88b5ba8SSam Ravnborg pbm->numa_node); 58*a88b5ba8SSam Ravnborg if (err) 59*a88b5ba8SSam Ravnborg return err; 60*a88b5ba8SSam Ravnborg 61*a88b5ba8SSam Ravnborg upa_writeq(__pa(iommu->page_table) | 0x7UL, iommu->iommu_tsbbase); 62*a88b5ba8SSam Ravnborg 63*a88b5ba8SSam Ravnborg control = upa_readq(iommu->iommu_control); 64*a88b5ba8SSam Ravnborg control |= (0x00000400 /* TSB cache snoop enable */ | 65*a88b5ba8SSam Ravnborg 0x00000300 /* Cache mode */ | 66*a88b5ba8SSam Ravnborg 0x00000002 /* Bypass enable */ | 67*a88b5ba8SSam Ravnborg 0x00000001 /* Translation enable */); 68*a88b5ba8SSam Ravnborg upa_writeq(control, iommu->iommu_control); 69*a88b5ba8SSam Ravnborg 70*a88b5ba8SSam Ravnborg return 0; 71*a88b5ba8SSam Ravnborg } 72*a88b5ba8SSam Ravnborg 73*a88b5ba8SSam Ravnborg #ifdef CONFIG_PCI_MSI 74*a88b5ba8SSam Ravnborg struct pci_msiq_entry { 75*a88b5ba8SSam Ravnborg u64 word0; 76*a88b5ba8SSam Ravnborg #define MSIQ_WORD0_RESV 0x8000000000000000UL 77*a88b5ba8SSam Ravnborg #define MSIQ_WORD0_FMT_TYPE 0x7f00000000000000UL 78*a88b5ba8SSam Ravnborg #define MSIQ_WORD0_FMT_TYPE_SHIFT 56 79*a88b5ba8SSam Ravnborg #define MSIQ_WORD0_LEN 0x00ffc00000000000UL 80*a88b5ba8SSam Ravnborg #define MSIQ_WORD0_LEN_SHIFT 46 81*a88b5ba8SSam Ravnborg #define MSIQ_WORD0_ADDR0 0x00003fff00000000UL 82*a88b5ba8SSam Ravnborg #define MSIQ_WORD0_ADDR0_SHIFT 32 83*a88b5ba8SSam Ravnborg #define MSIQ_WORD0_RID 0x00000000ffff0000UL 84*a88b5ba8SSam Ravnborg #define MSIQ_WORD0_RID_SHIFT 16 85*a88b5ba8SSam Ravnborg #define MSIQ_WORD0_DATA0 0x000000000000ffffUL 86*a88b5ba8SSam Ravnborg #define MSIQ_WORD0_DATA0_SHIFT 0 87*a88b5ba8SSam Ravnborg 88*a88b5ba8SSam Ravnborg #define MSIQ_TYPE_MSG 0x6 89*a88b5ba8SSam Ravnborg #define MSIQ_TYPE_MSI32 0xb 90*a88b5ba8SSam Ravnborg #define MSIQ_TYPE_MSI64 0xf 91*a88b5ba8SSam Ravnborg 92*a88b5ba8SSam Ravnborg u64 word1; 93*a88b5ba8SSam Ravnborg #define MSIQ_WORD1_ADDR1 0xffffffffffff0000UL 94*a88b5ba8SSam Ravnborg #define MSIQ_WORD1_ADDR1_SHIFT 16 95*a88b5ba8SSam Ravnborg #define MSIQ_WORD1_DATA1 0x000000000000ffffUL 96*a88b5ba8SSam Ravnborg #define MSIQ_WORD1_DATA1_SHIFT 0 97*a88b5ba8SSam Ravnborg 98*a88b5ba8SSam Ravnborg u64 resv[6]; 99*a88b5ba8SSam Ravnborg }; 100*a88b5ba8SSam Ravnborg 101*a88b5ba8SSam Ravnborg /* All MSI registers are offset from pbm->pbm_regs */ 102*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_BASE_ADDR_REG 0x010000UL 103*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_BASE_ADDR_ALL_ONES 0xfffc000000000000UL 104*a88b5ba8SSam Ravnborg 105*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_CONTROL_SET(EQ) (0x011000UL + (EQ) * 0x8UL) 106*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_CONTROL_SET_OFLOW 0x0200000000000000UL 107*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_CONTROL_SET_EN 0x0000100000000000UL 108*a88b5ba8SSam Ravnborg 109*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_CONTROL_CLEAR(EQ) (0x011200UL + (EQ) * 0x8UL) 110*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_CONTROL_CLEAR_OF 0x0200000000000000UL 111*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_CONTROL_CLEAR_E2I 0x0000800000000000UL 112*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_CONTROL_CLEAR_DIS 0x0000100000000000UL 113*a88b5ba8SSam Ravnborg 114*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_STATE(EQ) (0x011400UL + (EQ) * 0x8UL) 115*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_STATE_MASK 0x0000000000000007UL 116*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_STATE_IDLE 0x0000000000000001UL 117*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_STATE_ACTIVE 0x0000000000000002UL 118*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_STATE_ERROR 0x0000000000000004UL 119*a88b5ba8SSam Ravnborg 120*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_TAIL(EQ) (0x011600UL + (EQ) * 0x8UL) 121*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_TAIL_OFLOW 0x0200000000000000UL 122*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_TAIL_VAL 0x000000000000007fUL 123*a88b5ba8SSam Ravnborg 124*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_HEAD(EQ) (0x011800UL + (EQ) * 0x8UL) 125*a88b5ba8SSam Ravnborg #define EVENT_QUEUE_HEAD_VAL 0x000000000000007fUL 126*a88b5ba8SSam Ravnborg 127*a88b5ba8SSam Ravnborg #define MSI_MAP(MSI) (0x020000UL + (MSI) * 0x8UL) 128*a88b5ba8SSam Ravnborg #define MSI_MAP_VALID 0x8000000000000000UL 129*a88b5ba8SSam Ravnborg #define MSI_MAP_EQWR_N 0x4000000000000000UL 130*a88b5ba8SSam Ravnborg #define MSI_MAP_EQNUM 0x000000000000003fUL 131*a88b5ba8SSam Ravnborg 132*a88b5ba8SSam Ravnborg #define MSI_CLEAR(MSI) (0x028000UL + (MSI) * 0x8UL) 133*a88b5ba8SSam Ravnborg #define MSI_CLEAR_EQWR_N 0x4000000000000000UL 134*a88b5ba8SSam Ravnborg 135*a88b5ba8SSam Ravnborg #define IMONDO_DATA0 0x02C000UL 136*a88b5ba8SSam Ravnborg #define IMONDO_DATA0_DATA 0xffffffffffffffc0UL 137*a88b5ba8SSam Ravnborg 138*a88b5ba8SSam Ravnborg #define IMONDO_DATA1 0x02C008UL 139*a88b5ba8SSam Ravnborg #define IMONDO_DATA1_DATA 0xffffffffffffffffUL 140*a88b5ba8SSam Ravnborg 141*a88b5ba8SSam Ravnborg #define MSI_32BIT_ADDR 0x034000UL 142*a88b5ba8SSam Ravnborg #define MSI_32BIT_ADDR_VAL 0x00000000ffff0000UL 143*a88b5ba8SSam Ravnborg 144*a88b5ba8SSam Ravnborg #define MSI_64BIT_ADDR 0x034008UL 145*a88b5ba8SSam Ravnborg #define MSI_64BIT_ADDR_VAL 0xffffffffffff0000UL 146*a88b5ba8SSam Ravnborg 147*a88b5ba8SSam Ravnborg static int pci_fire_get_head(struct pci_pbm_info *pbm, unsigned long msiqid, 148*a88b5ba8SSam Ravnborg unsigned long *head) 149*a88b5ba8SSam Ravnborg { 150*a88b5ba8SSam Ravnborg *head = upa_readq(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); 151*a88b5ba8SSam Ravnborg return 0; 152*a88b5ba8SSam Ravnborg } 153*a88b5ba8SSam Ravnborg 154*a88b5ba8SSam Ravnborg static int pci_fire_dequeue_msi(struct pci_pbm_info *pbm, unsigned long msiqid, 155*a88b5ba8SSam Ravnborg unsigned long *head, unsigned long *msi) 156*a88b5ba8SSam Ravnborg { 157*a88b5ba8SSam Ravnborg unsigned long type_fmt, type, msi_num; 158*a88b5ba8SSam Ravnborg struct pci_msiq_entry *base, *ep; 159*a88b5ba8SSam Ravnborg 160*a88b5ba8SSam Ravnborg base = (pbm->msi_queues + ((msiqid - pbm->msiq_first) * 8192)); 161*a88b5ba8SSam Ravnborg ep = &base[*head]; 162*a88b5ba8SSam Ravnborg 163*a88b5ba8SSam Ravnborg if ((ep->word0 & MSIQ_WORD0_FMT_TYPE) == 0) 164*a88b5ba8SSam Ravnborg return 0; 165*a88b5ba8SSam Ravnborg 166*a88b5ba8SSam Ravnborg type_fmt = ((ep->word0 & MSIQ_WORD0_FMT_TYPE) >> 167*a88b5ba8SSam Ravnborg MSIQ_WORD0_FMT_TYPE_SHIFT); 168*a88b5ba8SSam Ravnborg type = (type_fmt >> 3); 169*a88b5ba8SSam Ravnborg if (unlikely(type != MSIQ_TYPE_MSI32 && 170*a88b5ba8SSam Ravnborg type != MSIQ_TYPE_MSI64)) 171*a88b5ba8SSam Ravnborg return -EINVAL; 172*a88b5ba8SSam Ravnborg 173*a88b5ba8SSam Ravnborg *msi = msi_num = ((ep->word0 & MSIQ_WORD0_DATA0) >> 174*a88b5ba8SSam Ravnborg MSIQ_WORD0_DATA0_SHIFT); 175*a88b5ba8SSam Ravnborg 176*a88b5ba8SSam Ravnborg upa_writeq(MSI_CLEAR_EQWR_N, pbm->pbm_regs + MSI_CLEAR(msi_num)); 177*a88b5ba8SSam Ravnborg 178*a88b5ba8SSam Ravnborg /* Clear the entry. */ 179*a88b5ba8SSam Ravnborg ep->word0 &= ~MSIQ_WORD0_FMT_TYPE; 180*a88b5ba8SSam Ravnborg 181*a88b5ba8SSam Ravnborg /* Go to next entry in ring. */ 182*a88b5ba8SSam Ravnborg (*head)++; 183*a88b5ba8SSam Ravnborg if (*head >= pbm->msiq_ent_count) 184*a88b5ba8SSam Ravnborg *head = 0; 185*a88b5ba8SSam Ravnborg 186*a88b5ba8SSam Ravnborg return 1; 187*a88b5ba8SSam Ravnborg } 188*a88b5ba8SSam Ravnborg 189*a88b5ba8SSam Ravnborg static int pci_fire_set_head(struct pci_pbm_info *pbm, unsigned long msiqid, 190*a88b5ba8SSam Ravnborg unsigned long head) 191*a88b5ba8SSam Ravnborg { 192*a88b5ba8SSam Ravnborg upa_writeq(head, pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); 193*a88b5ba8SSam Ravnborg return 0; 194*a88b5ba8SSam Ravnborg } 195*a88b5ba8SSam Ravnborg 196*a88b5ba8SSam Ravnborg static int pci_fire_msi_setup(struct pci_pbm_info *pbm, unsigned long msiqid, 197*a88b5ba8SSam Ravnborg unsigned long msi, int is_msi64) 198*a88b5ba8SSam Ravnborg { 199*a88b5ba8SSam Ravnborg u64 val; 200*a88b5ba8SSam Ravnborg 201*a88b5ba8SSam Ravnborg val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); 202*a88b5ba8SSam Ravnborg val &= ~(MSI_MAP_EQNUM); 203*a88b5ba8SSam Ravnborg val |= msiqid; 204*a88b5ba8SSam Ravnborg upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); 205*a88b5ba8SSam Ravnborg 206*a88b5ba8SSam Ravnborg upa_writeq(MSI_CLEAR_EQWR_N, pbm->pbm_regs + MSI_CLEAR(msi)); 207*a88b5ba8SSam Ravnborg 208*a88b5ba8SSam Ravnborg val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); 209*a88b5ba8SSam Ravnborg val |= MSI_MAP_VALID; 210*a88b5ba8SSam Ravnborg upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); 211*a88b5ba8SSam Ravnborg 212*a88b5ba8SSam Ravnborg return 0; 213*a88b5ba8SSam Ravnborg } 214*a88b5ba8SSam Ravnborg 215*a88b5ba8SSam Ravnborg static int pci_fire_msi_teardown(struct pci_pbm_info *pbm, unsigned long msi) 216*a88b5ba8SSam Ravnborg { 217*a88b5ba8SSam Ravnborg unsigned long msiqid; 218*a88b5ba8SSam Ravnborg u64 val; 219*a88b5ba8SSam Ravnborg 220*a88b5ba8SSam Ravnborg val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); 221*a88b5ba8SSam Ravnborg msiqid = (val & MSI_MAP_EQNUM); 222*a88b5ba8SSam Ravnborg 223*a88b5ba8SSam Ravnborg val &= ~MSI_MAP_VALID; 224*a88b5ba8SSam Ravnborg 225*a88b5ba8SSam Ravnborg upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); 226*a88b5ba8SSam Ravnborg 227*a88b5ba8SSam Ravnborg return 0; 228*a88b5ba8SSam Ravnborg } 229*a88b5ba8SSam Ravnborg 230*a88b5ba8SSam Ravnborg static int pci_fire_msiq_alloc(struct pci_pbm_info *pbm) 231*a88b5ba8SSam Ravnborg { 232*a88b5ba8SSam Ravnborg unsigned long pages, order, i; 233*a88b5ba8SSam Ravnborg 234*a88b5ba8SSam Ravnborg order = get_order(512 * 1024); 235*a88b5ba8SSam Ravnborg pages = __get_free_pages(GFP_KERNEL | __GFP_COMP, order); 236*a88b5ba8SSam Ravnborg if (pages == 0UL) { 237*a88b5ba8SSam Ravnborg printk(KERN_ERR "MSI: Cannot allocate MSI queues (o=%lu).\n", 238*a88b5ba8SSam Ravnborg order); 239*a88b5ba8SSam Ravnborg return -ENOMEM; 240*a88b5ba8SSam Ravnborg } 241*a88b5ba8SSam Ravnborg memset((char *)pages, 0, PAGE_SIZE << order); 242*a88b5ba8SSam Ravnborg pbm->msi_queues = (void *) pages; 243*a88b5ba8SSam Ravnborg 244*a88b5ba8SSam Ravnborg upa_writeq((EVENT_QUEUE_BASE_ADDR_ALL_ONES | 245*a88b5ba8SSam Ravnborg __pa(pbm->msi_queues)), 246*a88b5ba8SSam Ravnborg pbm->pbm_regs + EVENT_QUEUE_BASE_ADDR_REG); 247*a88b5ba8SSam Ravnborg 248*a88b5ba8SSam Ravnborg upa_writeq(pbm->portid << 6, pbm->pbm_regs + IMONDO_DATA0); 249*a88b5ba8SSam Ravnborg upa_writeq(0, pbm->pbm_regs + IMONDO_DATA1); 250*a88b5ba8SSam Ravnborg 251*a88b5ba8SSam Ravnborg upa_writeq(pbm->msi32_start, pbm->pbm_regs + MSI_32BIT_ADDR); 252*a88b5ba8SSam Ravnborg upa_writeq(pbm->msi64_start, pbm->pbm_regs + MSI_64BIT_ADDR); 253*a88b5ba8SSam Ravnborg 254*a88b5ba8SSam Ravnborg for (i = 0; i < pbm->msiq_num; i++) { 255*a88b5ba8SSam Ravnborg upa_writeq(0, pbm->pbm_regs + EVENT_QUEUE_HEAD(i)); 256*a88b5ba8SSam Ravnborg upa_writeq(0, pbm->pbm_regs + EVENT_QUEUE_TAIL(i)); 257*a88b5ba8SSam Ravnborg } 258*a88b5ba8SSam Ravnborg 259*a88b5ba8SSam Ravnborg return 0; 260*a88b5ba8SSam Ravnborg } 261*a88b5ba8SSam Ravnborg 262*a88b5ba8SSam Ravnborg static void pci_fire_msiq_free(struct pci_pbm_info *pbm) 263*a88b5ba8SSam Ravnborg { 264*a88b5ba8SSam Ravnborg unsigned long pages, order; 265*a88b5ba8SSam Ravnborg 266*a88b5ba8SSam Ravnborg order = get_order(512 * 1024); 267*a88b5ba8SSam Ravnborg pages = (unsigned long) pbm->msi_queues; 268*a88b5ba8SSam Ravnborg 269*a88b5ba8SSam Ravnborg free_pages(pages, order); 270*a88b5ba8SSam Ravnborg 271*a88b5ba8SSam Ravnborg pbm->msi_queues = NULL; 272*a88b5ba8SSam Ravnborg } 273*a88b5ba8SSam Ravnborg 274*a88b5ba8SSam Ravnborg static int pci_fire_msiq_build_irq(struct pci_pbm_info *pbm, 275*a88b5ba8SSam Ravnborg unsigned long msiqid, 276*a88b5ba8SSam Ravnborg unsigned long devino) 277*a88b5ba8SSam Ravnborg { 278*a88b5ba8SSam Ravnborg unsigned long cregs = (unsigned long) pbm->pbm_regs; 279*a88b5ba8SSam Ravnborg unsigned long imap_reg, iclr_reg, int_ctrlr; 280*a88b5ba8SSam Ravnborg unsigned int virt_irq; 281*a88b5ba8SSam Ravnborg int fixup; 282*a88b5ba8SSam Ravnborg u64 val; 283*a88b5ba8SSam Ravnborg 284*a88b5ba8SSam Ravnborg imap_reg = cregs + (0x001000UL + (devino * 0x08UL)); 285*a88b5ba8SSam Ravnborg iclr_reg = cregs + (0x001400UL + (devino * 0x08UL)); 286*a88b5ba8SSam Ravnborg 287*a88b5ba8SSam Ravnborg /* XXX iterate amongst the 4 IRQ controllers XXX */ 288*a88b5ba8SSam Ravnborg int_ctrlr = (1UL << 6); 289*a88b5ba8SSam Ravnborg 290*a88b5ba8SSam Ravnborg val = upa_readq(imap_reg); 291*a88b5ba8SSam Ravnborg val |= (1UL << 63) | int_ctrlr; 292*a88b5ba8SSam Ravnborg upa_writeq(val, imap_reg); 293*a88b5ba8SSam Ravnborg 294*a88b5ba8SSam Ravnborg fixup = ((pbm->portid << 6) | devino) - int_ctrlr; 295*a88b5ba8SSam Ravnborg 296*a88b5ba8SSam Ravnborg virt_irq = build_irq(fixup, iclr_reg, imap_reg); 297*a88b5ba8SSam Ravnborg if (!virt_irq) 298*a88b5ba8SSam Ravnborg return -ENOMEM; 299*a88b5ba8SSam Ravnborg 300*a88b5ba8SSam Ravnborg upa_writeq(EVENT_QUEUE_CONTROL_SET_EN, 301*a88b5ba8SSam Ravnborg pbm->pbm_regs + EVENT_QUEUE_CONTROL_SET(msiqid)); 302*a88b5ba8SSam Ravnborg 303*a88b5ba8SSam Ravnborg return virt_irq; 304*a88b5ba8SSam Ravnborg } 305*a88b5ba8SSam Ravnborg 306*a88b5ba8SSam Ravnborg static const struct sparc64_msiq_ops pci_fire_msiq_ops = { 307*a88b5ba8SSam Ravnborg .get_head = pci_fire_get_head, 308*a88b5ba8SSam Ravnborg .dequeue_msi = pci_fire_dequeue_msi, 309*a88b5ba8SSam Ravnborg .set_head = pci_fire_set_head, 310*a88b5ba8SSam Ravnborg .msi_setup = pci_fire_msi_setup, 311*a88b5ba8SSam Ravnborg .msi_teardown = pci_fire_msi_teardown, 312*a88b5ba8SSam Ravnborg .msiq_alloc = pci_fire_msiq_alloc, 313*a88b5ba8SSam Ravnborg .msiq_free = pci_fire_msiq_free, 314*a88b5ba8SSam Ravnborg .msiq_build_irq = pci_fire_msiq_build_irq, 315*a88b5ba8SSam Ravnborg }; 316*a88b5ba8SSam Ravnborg 317*a88b5ba8SSam Ravnborg static void pci_fire_msi_init(struct pci_pbm_info *pbm) 318*a88b5ba8SSam Ravnborg { 319*a88b5ba8SSam Ravnborg sparc64_pbm_msi_init(pbm, &pci_fire_msiq_ops); 320*a88b5ba8SSam Ravnborg } 321*a88b5ba8SSam Ravnborg #else /* CONFIG_PCI_MSI */ 322*a88b5ba8SSam Ravnborg static void pci_fire_msi_init(struct pci_pbm_info *pbm) 323*a88b5ba8SSam Ravnborg { 324*a88b5ba8SSam Ravnborg } 325*a88b5ba8SSam Ravnborg #endif /* !(CONFIG_PCI_MSI) */ 326*a88b5ba8SSam Ravnborg 327*a88b5ba8SSam Ravnborg /* Based at pbm->controller_regs */ 328*a88b5ba8SSam Ravnborg #define FIRE_PARITY_CONTROL 0x470010UL 329*a88b5ba8SSam Ravnborg #define FIRE_PARITY_ENAB 0x8000000000000000UL 330*a88b5ba8SSam Ravnborg #define FIRE_FATAL_RESET_CTL 0x471028UL 331*a88b5ba8SSam Ravnborg #define FIRE_FATAL_RESET_SPARE 0x0000000004000000UL 332*a88b5ba8SSam Ravnborg #define FIRE_FATAL_RESET_MB 0x0000000002000000UL 333*a88b5ba8SSam Ravnborg #define FIRE_FATAL_RESET_CPE 0x0000000000008000UL 334*a88b5ba8SSam Ravnborg #define FIRE_FATAL_RESET_APE 0x0000000000004000UL 335*a88b5ba8SSam Ravnborg #define FIRE_FATAL_RESET_PIO 0x0000000000000040UL 336*a88b5ba8SSam Ravnborg #define FIRE_FATAL_RESET_JW 0x0000000000000004UL 337*a88b5ba8SSam Ravnborg #define FIRE_FATAL_RESET_JI 0x0000000000000002UL 338*a88b5ba8SSam Ravnborg #define FIRE_FATAL_RESET_JR 0x0000000000000001UL 339*a88b5ba8SSam Ravnborg #define FIRE_CORE_INTR_ENABLE 0x471800UL 340*a88b5ba8SSam Ravnborg 341*a88b5ba8SSam Ravnborg /* Based at pbm->pbm_regs */ 342*a88b5ba8SSam Ravnborg #define FIRE_TLU_CTRL 0x80000UL 343*a88b5ba8SSam Ravnborg #define FIRE_TLU_CTRL_TIM 0x00000000da000000UL 344*a88b5ba8SSam Ravnborg #define FIRE_TLU_CTRL_QDET 0x0000000000000100UL 345*a88b5ba8SSam Ravnborg #define FIRE_TLU_CTRL_CFG 0x0000000000000001UL 346*a88b5ba8SSam Ravnborg #define FIRE_TLU_DEV_CTRL 0x90008UL 347*a88b5ba8SSam Ravnborg #define FIRE_TLU_LINK_CTRL 0x90020UL 348*a88b5ba8SSam Ravnborg #define FIRE_TLU_LINK_CTRL_CLK 0x0000000000000040UL 349*a88b5ba8SSam Ravnborg #define FIRE_LPU_RESET 0xe2008UL 350*a88b5ba8SSam Ravnborg #define FIRE_LPU_LLCFG 0xe2200UL 351*a88b5ba8SSam Ravnborg #define FIRE_LPU_LLCFG_VC0 0x0000000000000100UL 352*a88b5ba8SSam Ravnborg #define FIRE_LPU_FCTRL_UCTRL 0xe2240UL 353*a88b5ba8SSam Ravnborg #define FIRE_LPU_FCTRL_UCTRL_N 0x0000000000000002UL 354*a88b5ba8SSam Ravnborg #define FIRE_LPU_FCTRL_UCTRL_P 0x0000000000000001UL 355*a88b5ba8SSam Ravnborg #define FIRE_LPU_TXL_FIFOP 0xe2430UL 356*a88b5ba8SSam Ravnborg #define FIRE_LPU_LTSSM_CFG2 0xe2788UL 357*a88b5ba8SSam Ravnborg #define FIRE_LPU_LTSSM_CFG3 0xe2790UL 358*a88b5ba8SSam Ravnborg #define FIRE_LPU_LTSSM_CFG4 0xe2798UL 359*a88b5ba8SSam Ravnborg #define FIRE_LPU_LTSSM_CFG5 0xe27a0UL 360*a88b5ba8SSam Ravnborg #define FIRE_DMC_IENAB 0x31800UL 361*a88b5ba8SSam Ravnborg #define FIRE_DMC_DBG_SEL_A 0x53000UL 362*a88b5ba8SSam Ravnborg #define FIRE_DMC_DBG_SEL_B 0x53008UL 363*a88b5ba8SSam Ravnborg #define FIRE_PEC_IENAB 0x51800UL 364*a88b5ba8SSam Ravnborg 365*a88b5ba8SSam Ravnborg static void pci_fire_hw_init(struct pci_pbm_info *pbm) 366*a88b5ba8SSam Ravnborg { 367*a88b5ba8SSam Ravnborg u64 val; 368*a88b5ba8SSam Ravnborg 369*a88b5ba8SSam Ravnborg upa_writeq(FIRE_PARITY_ENAB, 370*a88b5ba8SSam Ravnborg pbm->controller_regs + FIRE_PARITY_CONTROL); 371*a88b5ba8SSam Ravnborg 372*a88b5ba8SSam Ravnborg upa_writeq((FIRE_FATAL_RESET_SPARE | 373*a88b5ba8SSam Ravnborg FIRE_FATAL_RESET_MB | 374*a88b5ba8SSam Ravnborg FIRE_FATAL_RESET_CPE | 375*a88b5ba8SSam Ravnborg FIRE_FATAL_RESET_APE | 376*a88b5ba8SSam Ravnborg FIRE_FATAL_RESET_PIO | 377*a88b5ba8SSam Ravnborg FIRE_FATAL_RESET_JW | 378*a88b5ba8SSam Ravnborg FIRE_FATAL_RESET_JI | 379*a88b5ba8SSam Ravnborg FIRE_FATAL_RESET_JR), 380*a88b5ba8SSam Ravnborg pbm->controller_regs + FIRE_FATAL_RESET_CTL); 381*a88b5ba8SSam Ravnborg 382*a88b5ba8SSam Ravnborg upa_writeq(~(u64)0, pbm->controller_regs + FIRE_CORE_INTR_ENABLE); 383*a88b5ba8SSam Ravnborg 384*a88b5ba8SSam Ravnborg val = upa_readq(pbm->pbm_regs + FIRE_TLU_CTRL); 385*a88b5ba8SSam Ravnborg val |= (FIRE_TLU_CTRL_TIM | 386*a88b5ba8SSam Ravnborg FIRE_TLU_CTRL_QDET | 387*a88b5ba8SSam Ravnborg FIRE_TLU_CTRL_CFG); 388*a88b5ba8SSam Ravnborg upa_writeq(val, pbm->pbm_regs + FIRE_TLU_CTRL); 389*a88b5ba8SSam Ravnborg upa_writeq(0, pbm->pbm_regs + FIRE_TLU_DEV_CTRL); 390*a88b5ba8SSam Ravnborg upa_writeq(FIRE_TLU_LINK_CTRL_CLK, 391*a88b5ba8SSam Ravnborg pbm->pbm_regs + FIRE_TLU_LINK_CTRL); 392*a88b5ba8SSam Ravnborg 393*a88b5ba8SSam Ravnborg upa_writeq(0, pbm->pbm_regs + FIRE_LPU_RESET); 394*a88b5ba8SSam Ravnborg upa_writeq(FIRE_LPU_LLCFG_VC0, pbm->pbm_regs + FIRE_LPU_LLCFG); 395*a88b5ba8SSam Ravnborg upa_writeq((FIRE_LPU_FCTRL_UCTRL_N | FIRE_LPU_FCTRL_UCTRL_P), 396*a88b5ba8SSam Ravnborg pbm->pbm_regs + FIRE_LPU_FCTRL_UCTRL); 397*a88b5ba8SSam Ravnborg upa_writeq(((0xffff << 16) | (0x0000 << 0)), 398*a88b5ba8SSam Ravnborg pbm->pbm_regs + FIRE_LPU_TXL_FIFOP); 399*a88b5ba8SSam Ravnborg upa_writeq(3000000, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG2); 400*a88b5ba8SSam Ravnborg upa_writeq(500000, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG3); 401*a88b5ba8SSam Ravnborg upa_writeq((2 << 16) | (140 << 8), 402*a88b5ba8SSam Ravnborg pbm->pbm_regs + FIRE_LPU_LTSSM_CFG4); 403*a88b5ba8SSam Ravnborg upa_writeq(0, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG5); 404*a88b5ba8SSam Ravnborg 405*a88b5ba8SSam Ravnborg upa_writeq(~(u64)0, pbm->pbm_regs + FIRE_DMC_IENAB); 406*a88b5ba8SSam Ravnborg upa_writeq(0, pbm->pbm_regs + FIRE_DMC_DBG_SEL_A); 407*a88b5ba8SSam Ravnborg upa_writeq(0, pbm->pbm_regs + FIRE_DMC_DBG_SEL_B); 408*a88b5ba8SSam Ravnborg 409*a88b5ba8SSam Ravnborg upa_writeq(~(u64)0, pbm->pbm_regs + FIRE_PEC_IENAB); 410*a88b5ba8SSam Ravnborg } 411*a88b5ba8SSam Ravnborg 412*a88b5ba8SSam Ravnborg static int __init pci_fire_pbm_init(struct pci_pbm_info *pbm, 413*a88b5ba8SSam Ravnborg struct of_device *op, u32 portid) 414*a88b5ba8SSam Ravnborg { 415*a88b5ba8SSam Ravnborg const struct linux_prom64_registers *regs; 416*a88b5ba8SSam Ravnborg struct device_node *dp = op->node; 417*a88b5ba8SSam Ravnborg int err; 418*a88b5ba8SSam Ravnborg 419*a88b5ba8SSam Ravnborg pbm->numa_node = -1; 420*a88b5ba8SSam Ravnborg 421*a88b5ba8SSam Ravnborg pbm->pci_ops = &sun4u_pci_ops; 422*a88b5ba8SSam Ravnborg pbm->config_space_reg_bits = 12; 423*a88b5ba8SSam Ravnborg 424*a88b5ba8SSam Ravnborg pbm->index = pci_num_pbms++; 425*a88b5ba8SSam Ravnborg 426*a88b5ba8SSam Ravnborg pbm->portid = portid; 427*a88b5ba8SSam Ravnborg pbm->op = op; 428*a88b5ba8SSam Ravnborg pbm->name = dp->full_name; 429*a88b5ba8SSam Ravnborg 430*a88b5ba8SSam Ravnborg regs = of_get_property(dp, "reg", NULL); 431*a88b5ba8SSam Ravnborg pbm->pbm_regs = regs[0].phys_addr; 432*a88b5ba8SSam Ravnborg pbm->controller_regs = regs[1].phys_addr - 0x410000UL; 433*a88b5ba8SSam Ravnborg 434*a88b5ba8SSam Ravnborg printk("%s: SUN4U PCIE Bus Module\n", pbm->name); 435*a88b5ba8SSam Ravnborg 436*a88b5ba8SSam Ravnborg pci_determine_mem_io_space(pbm); 437*a88b5ba8SSam Ravnborg 438*a88b5ba8SSam Ravnborg pci_get_pbm_props(pbm); 439*a88b5ba8SSam Ravnborg 440*a88b5ba8SSam Ravnborg pci_fire_hw_init(pbm); 441*a88b5ba8SSam Ravnborg 442*a88b5ba8SSam Ravnborg err = pci_fire_pbm_iommu_init(pbm); 443*a88b5ba8SSam Ravnborg if (err) 444*a88b5ba8SSam Ravnborg return err; 445*a88b5ba8SSam Ravnborg 446*a88b5ba8SSam Ravnborg pci_fire_msi_init(pbm); 447*a88b5ba8SSam Ravnborg 448*a88b5ba8SSam Ravnborg pbm->pci_bus = pci_scan_one_pbm(pbm, &op->dev); 449*a88b5ba8SSam Ravnborg 450*a88b5ba8SSam Ravnborg /* XXX register error interrupt handlers XXX */ 451*a88b5ba8SSam Ravnborg 452*a88b5ba8SSam Ravnborg pbm->next = pci_pbm_root; 453*a88b5ba8SSam Ravnborg pci_pbm_root = pbm; 454*a88b5ba8SSam Ravnborg 455*a88b5ba8SSam Ravnborg return 0; 456*a88b5ba8SSam Ravnborg } 457*a88b5ba8SSam Ravnborg 458*a88b5ba8SSam Ravnborg static int __devinit fire_probe(struct of_device *op, 459*a88b5ba8SSam Ravnborg const struct of_device_id *match) 460*a88b5ba8SSam Ravnborg { 461*a88b5ba8SSam Ravnborg struct device_node *dp = op->node; 462*a88b5ba8SSam Ravnborg struct pci_pbm_info *pbm; 463*a88b5ba8SSam Ravnborg struct iommu *iommu; 464*a88b5ba8SSam Ravnborg u32 portid; 465*a88b5ba8SSam Ravnborg int err; 466*a88b5ba8SSam Ravnborg 467*a88b5ba8SSam Ravnborg portid = of_getintprop_default(dp, "portid", 0xff); 468*a88b5ba8SSam Ravnborg 469*a88b5ba8SSam Ravnborg err = -ENOMEM; 470*a88b5ba8SSam Ravnborg pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); 471*a88b5ba8SSam Ravnborg if (!pbm) { 472*a88b5ba8SSam Ravnborg printk(KERN_ERR PFX "Cannot allocate pci_pbminfo.\n"); 473*a88b5ba8SSam Ravnborg goto out_err; 474*a88b5ba8SSam Ravnborg } 475*a88b5ba8SSam Ravnborg 476*a88b5ba8SSam Ravnborg iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); 477*a88b5ba8SSam Ravnborg if (!iommu) { 478*a88b5ba8SSam Ravnborg printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); 479*a88b5ba8SSam Ravnborg goto out_free_controller; 480*a88b5ba8SSam Ravnborg } 481*a88b5ba8SSam Ravnborg 482*a88b5ba8SSam Ravnborg pbm->iommu = iommu; 483*a88b5ba8SSam Ravnborg 484*a88b5ba8SSam Ravnborg err = pci_fire_pbm_init(pbm, op, portid); 485*a88b5ba8SSam Ravnborg if (err) 486*a88b5ba8SSam Ravnborg goto out_free_iommu; 487*a88b5ba8SSam Ravnborg 488*a88b5ba8SSam Ravnborg dev_set_drvdata(&op->dev, pbm); 489*a88b5ba8SSam Ravnborg 490*a88b5ba8SSam Ravnborg return 0; 491*a88b5ba8SSam Ravnborg 492*a88b5ba8SSam Ravnborg out_free_iommu: 493*a88b5ba8SSam Ravnborg kfree(pbm->iommu); 494*a88b5ba8SSam Ravnborg 495*a88b5ba8SSam Ravnborg out_free_controller: 496*a88b5ba8SSam Ravnborg kfree(pbm); 497*a88b5ba8SSam Ravnborg 498*a88b5ba8SSam Ravnborg out_err: 499*a88b5ba8SSam Ravnborg return err; 500*a88b5ba8SSam Ravnborg } 501*a88b5ba8SSam Ravnborg 502*a88b5ba8SSam Ravnborg static struct of_device_id __initdata fire_match[] = { 503*a88b5ba8SSam Ravnborg { 504*a88b5ba8SSam Ravnborg .name = "pci", 505*a88b5ba8SSam Ravnborg .compatible = "pciex108e,80f0", 506*a88b5ba8SSam Ravnborg }, 507*a88b5ba8SSam Ravnborg {}, 508*a88b5ba8SSam Ravnborg }; 509*a88b5ba8SSam Ravnborg 510*a88b5ba8SSam Ravnborg static struct of_platform_driver fire_driver = { 511*a88b5ba8SSam Ravnborg .name = DRIVER_NAME, 512*a88b5ba8SSam Ravnborg .match_table = fire_match, 513*a88b5ba8SSam Ravnborg .probe = fire_probe, 514*a88b5ba8SSam Ravnborg }; 515*a88b5ba8SSam Ravnborg 516*a88b5ba8SSam Ravnborg static int __init fire_init(void) 517*a88b5ba8SSam Ravnborg { 518*a88b5ba8SSam Ravnborg return of_register_driver(&fire_driver, &of_bus_type); 519*a88b5ba8SSam Ravnborg } 520*a88b5ba8SSam Ravnborg 521*a88b5ba8SSam Ravnborg subsys_initcall(fire_init); 522