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