1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <linux/types.h> 3 #include <linux/ioport.h> 4 #include <linux/slab.h> 5 #include <linux/export.h> 6 #include <linux/io.h> 7 #include <linux/mcb.h> 8 9 #include "mcb-internal.h" 10 11 #define for_each_chameleon_cell(dtype, p) \ 12 for ((dtype) = get_next_dtype((p)); \ 13 (dtype) != CHAMELEON_DTYPE_END; \ 14 (dtype) = get_next_dtype((p))) 15 16 static inline uint32_t get_next_dtype(void __iomem *p) 17 { 18 uint32_t dtype; 19 20 dtype = readl(p); 21 return dtype >> 28; 22 } 23 24 static int chameleon_parse_bdd(struct mcb_bus *bus, 25 struct chameleon_bar *cb, 26 void __iomem *base) 27 { 28 return 0; 29 } 30 31 static int chameleon_parse_gdd(struct mcb_bus *bus, 32 struct chameleon_bar *cb, 33 void __iomem *base, int bar_count) 34 { 35 struct chameleon_gdd __iomem *gdd = 36 (struct chameleon_gdd __iomem *) base; 37 struct mcb_device *mdev; 38 u32 dev_mapbase; 39 u32 offset; 40 u32 size; 41 int ret; 42 __le32 reg1; 43 __le32 reg2; 44 45 mdev = mcb_alloc_dev(bus); 46 if (!mdev) 47 return -ENOMEM; 48 49 reg1 = readl(&gdd->reg1); 50 reg2 = readl(&gdd->reg2); 51 offset = readl(&gdd->offset); 52 size = readl(&gdd->size); 53 54 mdev->id = GDD_DEV(reg1); 55 mdev->rev = GDD_REV(reg1); 56 mdev->var = GDD_VAR(reg1); 57 mdev->bar = GDD_BAR(reg2); 58 mdev->group = GDD_GRP(reg2); 59 mdev->inst = GDD_INS(reg2); 60 61 /* 62 * If the BAR is missing, dev_mapbase is zero, or if the 63 * device is IO mapped we just print a warning and go on with the 64 * next device, instead of completely stop the gdd parser 65 */ 66 if (mdev->bar > bar_count - 1) { 67 pr_info("No BAR for 16z%03d\n", mdev->id); 68 ret = 0; 69 goto err; 70 } 71 72 dev_mapbase = cb[mdev->bar].addr; 73 if (!dev_mapbase) { 74 pr_info("BAR not assigned for 16z%03d\n", mdev->id); 75 ret = 0; 76 goto err; 77 } 78 79 if (dev_mapbase & 0x01) { 80 pr_info("IO mapped Device (16z%03d) not yet supported\n", 81 mdev->id); 82 ret = 0; 83 goto err; 84 } 85 86 pr_debug("Found a 16z%03d\n", mdev->id); 87 88 mdev->irq.start = GDD_IRQ(reg1); 89 mdev->irq.end = GDD_IRQ(reg1); 90 mdev->irq.flags = IORESOURCE_IRQ; 91 92 mdev->mem.start = dev_mapbase + offset; 93 94 mdev->mem.end = mdev->mem.start + size - 1; 95 mdev->mem.flags = IORESOURCE_MEM; 96 97 ret = mcb_device_register(bus, mdev); 98 if (ret < 0) 99 goto err; 100 101 return 0; 102 103 err: 104 mcb_free_dev(mdev); 105 106 return ret; 107 } 108 109 static void chameleon_parse_bar(void __iomem *base, 110 struct chameleon_bar *cb, int bar_count) 111 { 112 char __iomem *p = base; 113 int i; 114 115 /* skip reg1 */ 116 p += sizeof(__le32); 117 118 for (i = 0; i < bar_count; i++) { 119 cb[i].addr = readl(p); 120 cb[i].size = readl(p + 4); 121 122 p += sizeof(struct chameleon_bar); 123 } 124 } 125 126 static int chameleon_get_bar(void __iomem **base, phys_addr_t mapbase, 127 struct chameleon_bar **cb) 128 { 129 struct chameleon_bar *c; 130 int bar_count; 131 __le32 reg; 132 u32 dtype; 133 134 /* 135 * For those devices which are not connected 136 * to the PCI Bus (e.g. LPC) there is a bar 137 * descriptor located directly after the 138 * chameleon header. This header is comparable 139 * to a PCI header. 140 */ 141 dtype = get_next_dtype(*base); 142 if (dtype == CHAMELEON_DTYPE_BAR) { 143 reg = readl(*base); 144 145 bar_count = BAR_CNT(reg); 146 if (bar_count <= 0 || bar_count > CHAMELEON_BAR_MAX) 147 return -ENODEV; 148 149 c = kcalloc(bar_count, sizeof(struct chameleon_bar), 150 GFP_KERNEL); 151 if (!c) 152 return -ENOMEM; 153 154 chameleon_parse_bar(*base, c, bar_count); 155 *base += BAR_DESC_SIZE(bar_count); 156 } else { 157 c = kzalloc(sizeof(struct chameleon_bar), GFP_KERNEL); 158 if (!c) 159 return -ENOMEM; 160 161 bar_count = 1; 162 c->addr = mapbase; 163 } 164 165 *cb = c; 166 167 return bar_count; 168 } 169 170 int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase, 171 void __iomem *base) 172 { 173 struct chameleon_fpga_header *header; 174 struct chameleon_bar *cb; 175 void __iomem *p = base; 176 int num_cells = 0; 177 uint32_t dtype; 178 int bar_count; 179 int ret; 180 u32 hsize; 181 u32 table_size; 182 183 hsize = sizeof(struct chameleon_fpga_header); 184 185 header = kzalloc(hsize, GFP_KERNEL); 186 if (!header) 187 return -ENOMEM; 188 189 /* Extract header information */ 190 memcpy_fromio(header, p, hsize); 191 /* We only support chameleon v2 at the moment */ 192 header->magic = le16_to_cpu(header->magic); 193 if (header->magic != CHAMELEONV2_MAGIC) { 194 pr_err("Unsupported chameleon version 0x%x\n", 195 header->magic); 196 ret = -ENODEV; 197 goto free_header; 198 } 199 p += hsize; 200 201 bus->revision = header->revision; 202 bus->model = header->model; 203 bus->minor = header->minor; 204 snprintf(bus->name, CHAMELEON_FILENAME_LEN + 1, "%s", 205 header->filename); 206 207 bar_count = chameleon_get_bar(&p, mapbase, &cb); 208 if (bar_count < 0) { 209 ret = bar_count; 210 goto free_header; 211 } 212 213 for_each_chameleon_cell(dtype, p) { 214 switch (dtype) { 215 case CHAMELEON_DTYPE_GENERAL: 216 ret = chameleon_parse_gdd(bus, cb, p, bar_count); 217 if (ret < 0) 218 goto free_bar; 219 p += sizeof(struct chameleon_gdd); 220 break; 221 case CHAMELEON_DTYPE_BRIDGE: 222 chameleon_parse_bdd(bus, cb, p); 223 p += sizeof(struct chameleon_bdd); 224 break; 225 case CHAMELEON_DTYPE_END: 226 break; 227 default: 228 pr_err("Invalid chameleon descriptor type 0x%x\n", 229 dtype); 230 ret = -EINVAL; 231 goto free_bar; 232 } 233 num_cells++; 234 } 235 236 if (num_cells == 0) { 237 ret = -EINVAL; 238 goto free_bar; 239 } 240 241 table_size = p - base; 242 pr_debug("%d cell(s) found. Chameleon table size: 0x%04x bytes\n", num_cells, table_size); 243 kfree(cb); 244 kfree(header); 245 return table_size; 246 247 free_bar: 248 kfree(cb); 249 free_header: 250 kfree(header); 251 252 return ret; 253 } 254 EXPORT_SYMBOL_NS_GPL(chameleon_parse_cells, MCB); 255