1*6f7f0b3dSMichael Neuling /* 2*6f7f0b3dSMichael Neuling * Copyright 2014 IBM Corp. 3*6f7f0b3dSMichael Neuling * 4*6f7f0b3dSMichael Neuling * This program is free software; you can redistribute it and/or 5*6f7f0b3dSMichael Neuling * modify it under the terms of the GNU General Public License 6*6f7f0b3dSMichael Neuling * as published by the Free Software Foundation; either version 7*6f7f0b3dSMichael Neuling * 2 of the License, or (at your option) any later version. 8*6f7f0b3dSMichael Neuling */ 9*6f7f0b3dSMichael Neuling 10*6f7f0b3dSMichael Neuling #include <linux/pci.h> 11*6f7f0b3dSMichael Neuling #include <misc/cxl.h> 12*6f7f0b3dSMichael Neuling #include "cxl.h" 13*6f7f0b3dSMichael Neuling 14*6f7f0b3dSMichael Neuling static int cxl_dma_set_mask(struct pci_dev *pdev, u64 dma_mask) 15*6f7f0b3dSMichael Neuling { 16*6f7f0b3dSMichael Neuling if (dma_mask < DMA_BIT_MASK(64)) { 17*6f7f0b3dSMichael Neuling pr_info("%s only 64bit DMA supported on CXL", __func__); 18*6f7f0b3dSMichael Neuling return -EIO; 19*6f7f0b3dSMichael Neuling } 20*6f7f0b3dSMichael Neuling 21*6f7f0b3dSMichael Neuling *(pdev->dev.dma_mask) = dma_mask; 22*6f7f0b3dSMichael Neuling return 0; 23*6f7f0b3dSMichael Neuling } 24*6f7f0b3dSMichael Neuling 25*6f7f0b3dSMichael Neuling static int cxl_pci_probe_mode(struct pci_bus *bus) 26*6f7f0b3dSMichael Neuling { 27*6f7f0b3dSMichael Neuling return PCI_PROBE_NORMAL; 28*6f7f0b3dSMichael Neuling } 29*6f7f0b3dSMichael Neuling 30*6f7f0b3dSMichael Neuling static int cxl_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) 31*6f7f0b3dSMichael Neuling { 32*6f7f0b3dSMichael Neuling return -ENODEV; 33*6f7f0b3dSMichael Neuling } 34*6f7f0b3dSMichael Neuling 35*6f7f0b3dSMichael Neuling static void cxl_teardown_msi_irqs(struct pci_dev *pdev) 36*6f7f0b3dSMichael Neuling { 37*6f7f0b3dSMichael Neuling /* 38*6f7f0b3dSMichael Neuling * MSI should never be set but need still need to provide this call 39*6f7f0b3dSMichael Neuling * back. 40*6f7f0b3dSMichael Neuling */ 41*6f7f0b3dSMichael Neuling } 42*6f7f0b3dSMichael Neuling 43*6f7f0b3dSMichael Neuling static bool cxl_pci_enable_device_hook(struct pci_dev *dev) 44*6f7f0b3dSMichael Neuling { 45*6f7f0b3dSMichael Neuling struct pci_controller *phb; 46*6f7f0b3dSMichael Neuling struct cxl_afu *afu; 47*6f7f0b3dSMichael Neuling struct cxl_context *ctx; 48*6f7f0b3dSMichael Neuling 49*6f7f0b3dSMichael Neuling phb = pci_bus_to_host(dev->bus); 50*6f7f0b3dSMichael Neuling afu = (struct cxl_afu *)phb->private_data; 51*6f7f0b3dSMichael Neuling set_dma_ops(&dev->dev, &dma_direct_ops); 52*6f7f0b3dSMichael Neuling set_dma_offset(&dev->dev, PAGE_OFFSET); 53*6f7f0b3dSMichael Neuling 54*6f7f0b3dSMichael Neuling /* 55*6f7f0b3dSMichael Neuling * Allocate a context to do cxl things too. If we eventually do real 56*6f7f0b3dSMichael Neuling * DMA ops, we'll need a default context to attach them to 57*6f7f0b3dSMichael Neuling */ 58*6f7f0b3dSMichael Neuling ctx = cxl_dev_context_init(dev); 59*6f7f0b3dSMichael Neuling if (!ctx) 60*6f7f0b3dSMichael Neuling return false; 61*6f7f0b3dSMichael Neuling dev->dev.archdata.cxl_ctx = ctx; 62*6f7f0b3dSMichael Neuling 63*6f7f0b3dSMichael Neuling return (cxl_afu_check_and_enable(afu) == 0); 64*6f7f0b3dSMichael Neuling } 65*6f7f0b3dSMichael Neuling 66*6f7f0b3dSMichael Neuling static void cxl_pci_disable_device(struct pci_dev *dev) 67*6f7f0b3dSMichael Neuling { 68*6f7f0b3dSMichael Neuling struct cxl_context *ctx = cxl_get_context(dev); 69*6f7f0b3dSMichael Neuling 70*6f7f0b3dSMichael Neuling if (ctx) { 71*6f7f0b3dSMichael Neuling if (ctx->status == STARTED) { 72*6f7f0b3dSMichael Neuling dev_err(&dev->dev, "Default context started\n"); 73*6f7f0b3dSMichael Neuling return; 74*6f7f0b3dSMichael Neuling } 75*6f7f0b3dSMichael Neuling cxl_release_context(ctx); 76*6f7f0b3dSMichael Neuling } 77*6f7f0b3dSMichael Neuling } 78*6f7f0b3dSMichael Neuling 79*6f7f0b3dSMichael Neuling static resource_size_t cxl_pci_window_alignment(struct pci_bus *bus, 80*6f7f0b3dSMichael Neuling unsigned long type) 81*6f7f0b3dSMichael Neuling { 82*6f7f0b3dSMichael Neuling return 1; 83*6f7f0b3dSMichael Neuling } 84*6f7f0b3dSMichael Neuling 85*6f7f0b3dSMichael Neuling static void cxl_pci_reset_secondary_bus(struct pci_dev *dev) 86*6f7f0b3dSMichael Neuling { 87*6f7f0b3dSMichael Neuling /* Should we do an AFU reset here ? */ 88*6f7f0b3dSMichael Neuling } 89*6f7f0b3dSMichael Neuling 90*6f7f0b3dSMichael Neuling static int cxl_pcie_cfg_record(u8 bus, u8 devfn) 91*6f7f0b3dSMichael Neuling { 92*6f7f0b3dSMichael Neuling return (bus << 8) + devfn; 93*6f7f0b3dSMichael Neuling } 94*6f7f0b3dSMichael Neuling 95*6f7f0b3dSMichael Neuling static unsigned long cxl_pcie_cfg_addr(struct pci_controller* phb, 96*6f7f0b3dSMichael Neuling u8 bus, u8 devfn, int offset) 97*6f7f0b3dSMichael Neuling { 98*6f7f0b3dSMichael Neuling int record = cxl_pcie_cfg_record(bus, devfn); 99*6f7f0b3dSMichael Neuling 100*6f7f0b3dSMichael Neuling return (unsigned long)phb->cfg_addr + ((unsigned long)phb->cfg_data * record) + offset; 101*6f7f0b3dSMichael Neuling } 102*6f7f0b3dSMichael Neuling 103*6f7f0b3dSMichael Neuling 104*6f7f0b3dSMichael Neuling static int cxl_pcie_config_info(struct pci_bus *bus, unsigned int devfn, 105*6f7f0b3dSMichael Neuling int offset, int len, 106*6f7f0b3dSMichael Neuling volatile void __iomem **ioaddr, 107*6f7f0b3dSMichael Neuling u32 *mask, int *shift) 108*6f7f0b3dSMichael Neuling { 109*6f7f0b3dSMichael Neuling struct pci_controller *phb; 110*6f7f0b3dSMichael Neuling struct cxl_afu *afu; 111*6f7f0b3dSMichael Neuling unsigned long addr; 112*6f7f0b3dSMichael Neuling 113*6f7f0b3dSMichael Neuling phb = pci_bus_to_host(bus); 114*6f7f0b3dSMichael Neuling afu = (struct cxl_afu *)phb->private_data; 115*6f7f0b3dSMichael Neuling if (phb == NULL) 116*6f7f0b3dSMichael Neuling return PCIBIOS_DEVICE_NOT_FOUND; 117*6f7f0b3dSMichael Neuling if (cxl_pcie_cfg_record(bus->number, devfn) > afu->crs_num) 118*6f7f0b3dSMichael Neuling return PCIBIOS_DEVICE_NOT_FOUND; 119*6f7f0b3dSMichael Neuling if (offset >= (unsigned long)phb->cfg_data) 120*6f7f0b3dSMichael Neuling return PCIBIOS_BAD_REGISTER_NUMBER; 121*6f7f0b3dSMichael Neuling addr = cxl_pcie_cfg_addr(phb, bus->number, devfn, offset); 122*6f7f0b3dSMichael Neuling 123*6f7f0b3dSMichael Neuling *ioaddr = (void *)(addr & ~0x3ULL); 124*6f7f0b3dSMichael Neuling *shift = ((addr & 0x3) * 8); 125*6f7f0b3dSMichael Neuling switch (len) { 126*6f7f0b3dSMichael Neuling case 1: 127*6f7f0b3dSMichael Neuling *mask = 0xff; 128*6f7f0b3dSMichael Neuling break; 129*6f7f0b3dSMichael Neuling case 2: 130*6f7f0b3dSMichael Neuling *mask = 0xffff; 131*6f7f0b3dSMichael Neuling break; 132*6f7f0b3dSMichael Neuling default: 133*6f7f0b3dSMichael Neuling *mask = 0xffffffff; 134*6f7f0b3dSMichael Neuling break; 135*6f7f0b3dSMichael Neuling } 136*6f7f0b3dSMichael Neuling return 0; 137*6f7f0b3dSMichael Neuling } 138*6f7f0b3dSMichael Neuling 139*6f7f0b3dSMichael Neuling static int cxl_pcie_read_config(struct pci_bus *bus, unsigned int devfn, 140*6f7f0b3dSMichael Neuling int offset, int len, u32 *val) 141*6f7f0b3dSMichael Neuling { 142*6f7f0b3dSMichael Neuling volatile void __iomem *ioaddr; 143*6f7f0b3dSMichael Neuling int shift, rc; 144*6f7f0b3dSMichael Neuling u32 mask; 145*6f7f0b3dSMichael Neuling 146*6f7f0b3dSMichael Neuling rc = cxl_pcie_config_info(bus, devfn, offset, len, &ioaddr, 147*6f7f0b3dSMichael Neuling &mask, &shift); 148*6f7f0b3dSMichael Neuling if (rc) 149*6f7f0b3dSMichael Neuling return rc; 150*6f7f0b3dSMichael Neuling 151*6f7f0b3dSMichael Neuling /* Can only read 32 bits */ 152*6f7f0b3dSMichael Neuling *val = (in_le32(ioaddr) >> shift) & mask; 153*6f7f0b3dSMichael Neuling return PCIBIOS_SUCCESSFUL; 154*6f7f0b3dSMichael Neuling } 155*6f7f0b3dSMichael Neuling 156*6f7f0b3dSMichael Neuling static int cxl_pcie_write_config(struct pci_bus *bus, unsigned int devfn, 157*6f7f0b3dSMichael Neuling int offset, int len, u32 val) 158*6f7f0b3dSMichael Neuling { 159*6f7f0b3dSMichael Neuling volatile void __iomem *ioaddr; 160*6f7f0b3dSMichael Neuling u32 v, mask; 161*6f7f0b3dSMichael Neuling int shift, rc; 162*6f7f0b3dSMichael Neuling 163*6f7f0b3dSMichael Neuling rc = cxl_pcie_config_info(bus, devfn, offset, len, &ioaddr, 164*6f7f0b3dSMichael Neuling &mask, &shift); 165*6f7f0b3dSMichael Neuling if (rc) 166*6f7f0b3dSMichael Neuling return rc; 167*6f7f0b3dSMichael Neuling 168*6f7f0b3dSMichael Neuling /* Can only write 32 bits so do read-modify-write */ 169*6f7f0b3dSMichael Neuling mask <<= shift; 170*6f7f0b3dSMichael Neuling val <<= shift; 171*6f7f0b3dSMichael Neuling 172*6f7f0b3dSMichael Neuling v = (in_le32(ioaddr) & ~mask) || (val & mask); 173*6f7f0b3dSMichael Neuling 174*6f7f0b3dSMichael Neuling out_le32(ioaddr, v); 175*6f7f0b3dSMichael Neuling return PCIBIOS_SUCCESSFUL; 176*6f7f0b3dSMichael Neuling } 177*6f7f0b3dSMichael Neuling 178*6f7f0b3dSMichael Neuling static struct pci_ops cxl_pcie_pci_ops = 179*6f7f0b3dSMichael Neuling { 180*6f7f0b3dSMichael Neuling .read = cxl_pcie_read_config, 181*6f7f0b3dSMichael Neuling .write = cxl_pcie_write_config, 182*6f7f0b3dSMichael Neuling }; 183*6f7f0b3dSMichael Neuling 184*6f7f0b3dSMichael Neuling 185*6f7f0b3dSMichael Neuling static struct pci_controller_ops cxl_pci_controller_ops = 186*6f7f0b3dSMichael Neuling { 187*6f7f0b3dSMichael Neuling .probe_mode = cxl_pci_probe_mode, 188*6f7f0b3dSMichael Neuling .enable_device_hook = cxl_pci_enable_device_hook, 189*6f7f0b3dSMichael Neuling .disable_device = cxl_pci_disable_device, 190*6f7f0b3dSMichael Neuling .release_device = cxl_pci_disable_device, 191*6f7f0b3dSMichael Neuling .window_alignment = cxl_pci_window_alignment, 192*6f7f0b3dSMichael Neuling .reset_secondary_bus = cxl_pci_reset_secondary_bus, 193*6f7f0b3dSMichael Neuling .setup_msi_irqs = cxl_setup_msi_irqs, 194*6f7f0b3dSMichael Neuling .teardown_msi_irqs = cxl_teardown_msi_irqs, 195*6f7f0b3dSMichael Neuling .dma_set_mask = cxl_dma_set_mask, 196*6f7f0b3dSMichael Neuling }; 197*6f7f0b3dSMichael Neuling 198*6f7f0b3dSMichael Neuling int cxl_pci_vphb_add(struct cxl_afu *afu) 199*6f7f0b3dSMichael Neuling { 200*6f7f0b3dSMichael Neuling struct pci_dev *phys_dev; 201*6f7f0b3dSMichael Neuling struct pci_controller *phb, *phys_phb; 202*6f7f0b3dSMichael Neuling 203*6f7f0b3dSMichael Neuling phys_dev = to_pci_dev(afu->adapter->dev.parent); 204*6f7f0b3dSMichael Neuling phys_phb = pci_bus_to_host(phys_dev->bus); 205*6f7f0b3dSMichael Neuling 206*6f7f0b3dSMichael Neuling /* Alloc and setup PHB data structure */ 207*6f7f0b3dSMichael Neuling phb = pcibios_alloc_controller(phys_phb->dn); 208*6f7f0b3dSMichael Neuling 209*6f7f0b3dSMichael Neuling if (!phb) 210*6f7f0b3dSMichael Neuling return -ENODEV; 211*6f7f0b3dSMichael Neuling 212*6f7f0b3dSMichael Neuling /* Setup parent in sysfs */ 213*6f7f0b3dSMichael Neuling phb->parent = &phys_dev->dev; 214*6f7f0b3dSMichael Neuling 215*6f7f0b3dSMichael Neuling /* Setup the PHB using arch provided callback */ 216*6f7f0b3dSMichael Neuling phb->ops = &cxl_pcie_pci_ops; 217*6f7f0b3dSMichael Neuling phb->cfg_addr = afu->afu_desc_mmio + afu->crs_offset; 218*6f7f0b3dSMichael Neuling phb->cfg_data = (void *)(u64)afu->crs_len; 219*6f7f0b3dSMichael Neuling phb->private_data = afu; 220*6f7f0b3dSMichael Neuling phb->controller_ops = cxl_pci_controller_ops; 221*6f7f0b3dSMichael Neuling 222*6f7f0b3dSMichael Neuling /* Scan the bus */ 223*6f7f0b3dSMichael Neuling pcibios_scan_phb(phb); 224*6f7f0b3dSMichael Neuling if (phb->bus == NULL) 225*6f7f0b3dSMichael Neuling return -ENXIO; 226*6f7f0b3dSMichael Neuling 227*6f7f0b3dSMichael Neuling /* Claim resources. This might need some rework as well depending 228*6f7f0b3dSMichael Neuling * whether we are doing probe-only or not, like assigning unassigned 229*6f7f0b3dSMichael Neuling * resources etc... 230*6f7f0b3dSMichael Neuling */ 231*6f7f0b3dSMichael Neuling pcibios_claim_one_bus(phb->bus); 232*6f7f0b3dSMichael Neuling 233*6f7f0b3dSMichael Neuling /* Add probed PCI devices to the device model */ 234*6f7f0b3dSMichael Neuling pci_bus_add_devices(phb->bus); 235*6f7f0b3dSMichael Neuling 236*6f7f0b3dSMichael Neuling afu->phb = phb; 237*6f7f0b3dSMichael Neuling 238*6f7f0b3dSMichael Neuling return 0; 239*6f7f0b3dSMichael Neuling } 240*6f7f0b3dSMichael Neuling 241*6f7f0b3dSMichael Neuling 242*6f7f0b3dSMichael Neuling void cxl_pci_vphb_remove(struct cxl_afu *afu) 243*6f7f0b3dSMichael Neuling { 244*6f7f0b3dSMichael Neuling struct pci_controller *phb; 245*6f7f0b3dSMichael Neuling 246*6f7f0b3dSMichael Neuling /* If there is no configuration record we won't have one of these */ 247*6f7f0b3dSMichael Neuling if (!afu || !afu->phb) 248*6f7f0b3dSMichael Neuling return; 249*6f7f0b3dSMichael Neuling 250*6f7f0b3dSMichael Neuling phb = afu->phb; 251*6f7f0b3dSMichael Neuling 252*6f7f0b3dSMichael Neuling pci_remove_root_bus(phb->bus); 253*6f7f0b3dSMichael Neuling } 254*6f7f0b3dSMichael Neuling 255*6f7f0b3dSMichael Neuling struct cxl_afu *cxl_pci_to_afu(struct pci_dev *dev) 256*6f7f0b3dSMichael Neuling { 257*6f7f0b3dSMichael Neuling struct pci_controller *phb; 258*6f7f0b3dSMichael Neuling 259*6f7f0b3dSMichael Neuling phb = pci_bus_to_host(dev->bus); 260*6f7f0b3dSMichael Neuling 261*6f7f0b3dSMichael Neuling return (struct cxl_afu *)phb->private_data; 262*6f7f0b3dSMichael Neuling } 263*6f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_pci_to_afu); 264*6f7f0b3dSMichael Neuling 265*6f7f0b3dSMichael Neuling unsigned int cxl_pci_to_cfg_record(struct pci_dev *dev) 266*6f7f0b3dSMichael Neuling { 267*6f7f0b3dSMichael Neuling return cxl_pcie_cfg_record(dev->bus->number, dev->devfn); 268*6f7f0b3dSMichael Neuling } 269*6f7f0b3dSMichael Neuling EXPORT_SYMBOL_GPL(cxl_pci_to_cfg_record); 270