1 // SPDX-License-Identifier: GPL-2.0+ 2 // Copyright 2017 IBM Corp. 3 #include <asm/pnv-ocxl.h> 4 #include <asm/opal.h> 5 #include "pci.h" 6 7 #define PNV_OCXL_TL_P9_RECV_CAP 0x000000000000000Full 8 /* PASIDs are 20-bit, but on P9, NPU can only handle 15 bits */ 9 #define PNV_OCXL_PASID_BITS 15 10 #define PNV_OCXL_PASID_MAX ((1 << PNV_OCXL_PASID_BITS) - 1) 11 12 13 static void set_templ_rate(unsigned int templ, unsigned int rate, char *buf) 14 { 15 int shift, idx; 16 17 WARN_ON(templ > PNV_OCXL_TL_MAX_TEMPLATE); 18 idx = (PNV_OCXL_TL_MAX_TEMPLATE - templ) / 2; 19 shift = 4 * (1 - ((PNV_OCXL_TL_MAX_TEMPLATE - templ) % 2)); 20 buf[idx] |= rate << shift; 21 } 22 23 int pnv_ocxl_get_tl_cap(struct pci_dev *dev, long *cap, 24 char *rate_buf, int rate_buf_size) 25 { 26 if (rate_buf_size != PNV_OCXL_TL_RATE_BUF_SIZE) 27 return -EINVAL; 28 /* 29 * The TL capabilities are a characteristic of the NPU, so 30 * we go with hard-coded values. 31 * 32 * The receiving rate of each template is encoded on 4 bits. 33 * 34 * On P9: 35 * - templates 0 -> 3 are supported 36 * - templates 0, 1 and 3 have a 0 receiving rate 37 * - template 2 has receiving rate of 1 (extra cycle) 38 */ 39 memset(rate_buf, 0, rate_buf_size); 40 set_templ_rate(2, 1, rate_buf); 41 *cap = PNV_OCXL_TL_P9_RECV_CAP; 42 return 0; 43 } 44 EXPORT_SYMBOL_GPL(pnv_ocxl_get_tl_cap); 45 46 int pnv_ocxl_set_tl_conf(struct pci_dev *dev, long cap, 47 uint64_t rate_buf_phys, int rate_buf_size) 48 { 49 struct pci_controller *hose = pci_bus_to_host(dev->bus); 50 struct pnv_phb *phb = hose->private_data; 51 int rc; 52 53 if (rate_buf_size != PNV_OCXL_TL_RATE_BUF_SIZE) 54 return -EINVAL; 55 56 rc = opal_npu_tl_set(phb->opal_id, dev->devfn, cap, 57 rate_buf_phys, rate_buf_size); 58 if (rc) { 59 dev_err(&dev->dev, "Can't configure host TL: %d\n", rc); 60 return -EINVAL; 61 } 62 return 0; 63 } 64 EXPORT_SYMBOL_GPL(pnv_ocxl_set_tl_conf); 65 66 int pnv_ocxl_get_xsl_irq(struct pci_dev *dev, int *hwirq) 67 { 68 int rc; 69 70 rc = of_property_read_u32(dev->dev.of_node, "ibm,opal-xsl-irq", hwirq); 71 if (rc) { 72 dev_err(&dev->dev, 73 "Can't get translation interrupt for device\n"); 74 return rc; 75 } 76 return 0; 77 } 78 EXPORT_SYMBOL_GPL(pnv_ocxl_get_xsl_irq); 79 80 void pnv_ocxl_unmap_xsl_regs(void __iomem *dsisr, void __iomem *dar, 81 void __iomem *tfc, void __iomem *pe_handle) 82 { 83 iounmap(dsisr); 84 iounmap(dar); 85 iounmap(tfc); 86 iounmap(pe_handle); 87 } 88 EXPORT_SYMBOL_GPL(pnv_ocxl_unmap_xsl_regs); 89 90 int pnv_ocxl_map_xsl_regs(struct pci_dev *dev, void __iomem **dsisr, 91 void __iomem **dar, void __iomem **tfc, 92 void __iomem **pe_handle) 93 { 94 u64 reg; 95 int i, j, rc = 0; 96 void __iomem *regs[4]; 97 98 /* 99 * opal stores the mmio addresses of the DSISR, DAR, TFC and 100 * PE_HANDLE registers in a device tree property, in that 101 * order 102 */ 103 for (i = 0; i < 4; i++) { 104 rc = of_property_read_u64_index(dev->dev.of_node, 105 "ibm,opal-xsl-mmio", i, ®); 106 if (rc) 107 break; 108 regs[i] = ioremap(reg, 8); 109 if (!regs[i]) { 110 rc = -EINVAL; 111 break; 112 } 113 } 114 if (rc) { 115 dev_err(&dev->dev, "Can't map translation mmio registers\n"); 116 for (j = i - 1; j >= 0; j--) 117 iounmap(regs[j]); 118 } else { 119 *dsisr = regs[0]; 120 *dar = regs[1]; 121 *tfc = regs[2]; 122 *pe_handle = regs[3]; 123 } 124 return rc; 125 } 126 EXPORT_SYMBOL_GPL(pnv_ocxl_map_xsl_regs); 127 128 struct spa_data { 129 u64 phb_opal_id; 130 u32 bdfn; 131 }; 132 133 int pnv_ocxl_spa_setup(struct pci_dev *dev, void *spa_mem, int PE_mask, 134 void **platform_data) 135 { 136 struct pci_controller *hose = pci_bus_to_host(dev->bus); 137 struct pnv_phb *phb = hose->private_data; 138 struct spa_data *data; 139 u32 bdfn; 140 int rc; 141 142 data = kzalloc(sizeof(*data), GFP_KERNEL); 143 if (!data) 144 return -ENOMEM; 145 146 bdfn = (dev->bus->number << 8) | dev->devfn; 147 rc = opal_npu_spa_setup(phb->opal_id, bdfn, virt_to_phys(spa_mem), 148 PE_mask); 149 if (rc) { 150 dev_err(&dev->dev, "Can't setup Shared Process Area: %d\n", rc); 151 kfree(data); 152 return rc; 153 } 154 data->phb_opal_id = phb->opal_id; 155 data->bdfn = bdfn; 156 *platform_data = (void *) data; 157 return 0; 158 } 159 EXPORT_SYMBOL_GPL(pnv_ocxl_spa_setup); 160 161 void pnv_ocxl_spa_release(void *platform_data) 162 { 163 struct spa_data *data = (struct spa_data *) platform_data; 164 int rc; 165 166 rc = opal_npu_spa_setup(data->phb_opal_id, data->bdfn, 0, 0); 167 WARN_ON(rc); 168 kfree(data); 169 } 170 EXPORT_SYMBOL_GPL(pnv_ocxl_spa_release); 171 172 int pnv_ocxl_spa_remove_pe(void *platform_data, int pe_handle) 173 { 174 struct spa_data *data = (struct spa_data *) platform_data; 175 int rc; 176 177 rc = opal_npu_spa_clear_cache(data->phb_opal_id, data->bdfn, pe_handle); 178 return rc; 179 } 180 EXPORT_SYMBOL_GPL(pnv_ocxl_spa_remove_pe); 181