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 return ret; 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 = kzalloc_objs(struct chameleon_bar, bar_count, GFP_KERNEL); 150 if (!c) 151 return -ENOMEM; 152 153 chameleon_parse_bar(*base, c, bar_count); 154 *base += BAR_DESC_SIZE(bar_count); 155 } else { 156 c = kzalloc_obj(struct chameleon_bar, GFP_KERNEL); 157 if (!c) 158 return -ENOMEM; 159 160 bar_count = 1; 161 c->addr = mapbase; 162 } 163 164 *cb = c; 165 166 return bar_count; 167 } 168 169 int chameleon_parse_cells(struct mcb_bus *bus, phys_addr_t mapbase, 170 void __iomem *base) 171 { 172 struct chameleon_fpga_header *header; 173 struct chameleon_bar *cb; 174 void __iomem *p = base; 175 int num_cells = 0; 176 uint32_t dtype; 177 int bar_count; 178 int ret; 179 u32 hsize; 180 u32 table_size; 181 182 hsize = sizeof(struct chameleon_fpga_header); 183 184 header = kzalloc(hsize, GFP_KERNEL); 185 if (!header) 186 return -ENOMEM; 187 188 /* Extract header information */ 189 memcpy_fromio(header, p, hsize); 190 /* We only support chameleon v2 at the moment */ 191 header->magic = le16_to_cpu(header->magic); 192 if (header->magic != CHAMELEONV2_MAGIC) { 193 pr_err("Unsupported chameleon version 0x%x\n", 194 header->magic); 195 ret = -ENODEV; 196 goto free_header; 197 } 198 p += hsize; 199 200 bus->revision = header->revision; 201 bus->model = header->model; 202 bus->minor = header->minor; 203 snprintf(bus->name, CHAMELEON_FILENAME_LEN + 1, "%s", 204 header->filename); 205 206 bar_count = chameleon_get_bar(&p, mapbase, &cb); 207 if (bar_count < 0) { 208 ret = bar_count; 209 goto free_header; 210 } 211 212 for_each_chameleon_cell(dtype, p) { 213 switch (dtype) { 214 case CHAMELEON_DTYPE_GENERAL: 215 ret = chameleon_parse_gdd(bus, cb, p, bar_count); 216 if (ret < 0) 217 goto free_bar; 218 p += sizeof(struct chameleon_gdd); 219 break; 220 case CHAMELEON_DTYPE_BRIDGE: 221 chameleon_parse_bdd(bus, cb, p); 222 p += sizeof(struct chameleon_bdd); 223 break; 224 case CHAMELEON_DTYPE_END: 225 break; 226 default: 227 pr_err("Invalid chameleon descriptor type 0x%x\n", 228 dtype); 229 ret = -EINVAL; 230 goto free_bar; 231 } 232 num_cells++; 233 } 234 235 if (num_cells == 0) { 236 ret = -EINVAL; 237 goto free_bar; 238 } 239 240 table_size = p - base; 241 pr_debug("%d cell(s) found. Chameleon table size: 0x%04x bytes\n", num_cells, table_size); 242 kfree(cb); 243 kfree(header); 244 return table_size; 245 246 free_bar: 247 kfree(cb); 248 free_header: 249 kfree(header); 250 251 return ret; 252 } 253 EXPORT_SYMBOL_NS_GPL(chameleon_parse_cells, "MCB"); 254