1 /*
2 * Aspeed PCIe host controller
3 *
4 * Copyright (c) 2022 Cédric Le Goater <clg@kaod.org>
5 *
6 * This code is licensed under the GPL version 2 or later. See
7 * the COPYING file in the top-level directory.
8 */
9
10 #include "qemu/osdep.h"
11 #include "qemu/module.h"
12 #include "qemu/units.h"
13 #include "qemu/log.h"
14 #include "qapi/error.h"
15 #include "hw/qdev-properties.h"
16 #include "hw/irq.h"
17 #include "hw/pci-host/aspeed_pcie.h"
18 #include "hw/pci/msi.h"
19
20 #include "trace.h"
21
22 #define TO_REG(offset) ((offset) >> 2)
23
24 #define PCI_VENDOR_ID_ASPEED 0x1A03
25 #define PCI_DEVICE_ID_AST2600_RC 0x1150
26
27 /*
28 * RC
29 */
30
31 #define ASPEED_PCIE_RC_CTRL 0x00
32 #define ASPEED_PCIE_RC_CTRL_RCL BIT(0)
33 #define ASPEED_PCIE_RC_CTRL_RCL_RX BIT(1)
34 #define ASPEED_PCIE_RC_CTRL_RX_WAIT_FW BIT(2)
35 #define ASPEED_PCIE_RC_CTRL_RX_UNLOCK BIT(4)
36 #define ASPEED_PCIE_RC_CTRL_RX_MSI BIT(6)
37 #define ASPEED_PCIE_RC_CTRL_RX_MSI_SELECT BIT(7)
38 #define ASPEED_PCIE_RC_CTRL_RX_LINEAR BIT(8)
39 #define ASPEED_PCIE_RC_CTRL_RX_DMA BIT(9)
40 #define ASPEED_PCIE_RC_CTRL_RX_TAG_MASK 0x00ff0000
41
42 #define ASPEED_PCIE_RC_INT_ENABLE 0x04
43 #define ASPEED_PCIE_RC_INT_ENABLE_INTA BIT(0)
44 #define ASPEED_PCIE_RC_INT_ENABLE_INTB BIT(1)
45 #define ASPEED_PCIE_RC_INT_ENABLE_INTC BIT(2)
46 #define ASPEED_PCIE_RC_INT_ENABLE_INTD BIT(3)
47 #define ASPEED_PCIE_RC_INT_ENABLE_RX BIT(4)
48 #define ASPEED_PCIE_RC_INT_STATUS 0x08
49 #define ASPEED_PCIE_RC_INT_STATUS_INTA BIT(0)
50 #define ASPEED_PCIE_RC_INT_STATUS_INTB BIT(1)
51 #define ASPEED_PCIE_RC_INT_STATUS_INTC BIT(2)
52 #define ASPEED_PCIE_RC_INT_STATUS_INTD BIT(3)
53 #define ASPEED_PCIE_RC_INT_STATUS_INTX_MASK 0xf
54 #define ASPEED_PCIE_RC_INT_STATUS_RX BIT(4)
55
56 #define ASPEED_PCIE_RC_RX_DATA 0x0C
57 #define ASPEED_PCIE_RC_RX_DW0 0x10
58 #define ASPEED_PCIE_RC_RX_DW1 0x14
59 #define ASPEED_PCIE_RC_RX_DW2 0x18
60 #define ASPEED_PCIE_RC_RX_DW3 0x1C
61 #define ASPEED_PCIE_RC_MSI_ENABLE0 0x20
62 #define ASPEED_PCIE_RC_MSI_ENABLE1 0x24
63 #define ASPEED_PCIE_RC_MSI_STATUS0 0x28
64 #define ASPEED_PCIE_RC_MSI_STATUS1 0x2C
65 #define ASPEED_PCIE_RC_TX_TAG 0x3C
66
aspeed_pcie_rc_update_irq(AspeedPCIERc * s)67 static void aspeed_pcie_rc_update_irq(AspeedPCIERc *s)
68 {
69 bool intx = !!(s->regs[TO_REG(ASPEED_PCIE_RC_INT_STATUS)] &
70 s->regs[TO_REG(ASPEED_PCIE_RC_INT_ENABLE)]);
71 bool msi0 = !!(s->regs[TO_REG(ASPEED_PCIE_RC_MSI_STATUS0)] &
72 s->regs[TO_REG(ASPEED_PCIE_RC_MSI_ENABLE0)]);
73 bool msi1 = !!(s->regs[TO_REG(ASPEED_PCIE_RC_MSI_STATUS1)] &
74 s->regs[TO_REG(ASPEED_PCIE_RC_MSI_ENABLE1)]);
75 bool level = intx || msi0 || msi1;
76
77 qemu_set_irq(s->irq, level);
78 }
79
aspeed_pcie_rc_read(void * opaque,hwaddr addr,unsigned int size)80 static uint64_t aspeed_pcie_rc_read(void *opaque, hwaddr addr,
81 unsigned int size)
82 {
83 AspeedPCIERc *s = ASPEED_PCIE_RC(opaque);
84 uint64_t val = 0;
85
86 switch (addr) {
87 case ASPEED_PCIE_RC_CTRL:
88 case ASPEED_PCIE_RC_INT_ENABLE:
89 case ASPEED_PCIE_RC_INT_STATUS:
90 case ASPEED_PCIE_RC_RX_DATA:
91 case ASPEED_PCIE_RC_RX_DW0:
92 case ASPEED_PCIE_RC_RX_DW1:
93 case ASPEED_PCIE_RC_RX_DW2:
94 case ASPEED_PCIE_RC_RX_DW3:
95 case ASPEED_PCIE_RC_MSI_ENABLE0:
96 case ASPEED_PCIE_RC_MSI_ENABLE1:
97 case ASPEED_PCIE_RC_MSI_STATUS0:
98 case ASPEED_PCIE_RC_MSI_STATUS1:
99 case ASPEED_PCIE_RC_TX_TAG:
100 val = s->regs[TO_REG(addr)];
101 break;
102
103 default:
104 qemu_log_mask(LOG_GUEST_ERROR,
105 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
106 __func__, addr);
107 break;
108 }
109
110 trace_aspeed_pcie_rc_read(addr, val);
111 return val;
112 }
113
aspeed_pcie_rc_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)114 static void aspeed_pcie_rc_write(void *opaque, hwaddr addr, uint64_t data,
115 unsigned int size)
116 {
117 AspeedPCIERc *s = ASPEED_PCIE_RC(opaque);
118
119 trace_aspeed_pcie_rc_write(addr, data);
120
121 switch (addr) {
122 case ASPEED_PCIE_RC_CTRL: /* TODO: unlock/lock RX */
123 case ASPEED_PCIE_RC_INT_ENABLE:
124 case ASPEED_PCIE_RC_MSI_ENABLE0:
125 case ASPEED_PCIE_RC_MSI_ENABLE1:
126 case ASPEED_PCIE_RC_TX_TAG:
127 s->regs[TO_REG(addr)] = data;
128 break;
129 case ASPEED_PCIE_RC_MSI_STATUS0:
130 case ASPEED_PCIE_RC_MSI_STATUS1:
131 s->regs[TO_REG(addr)] &= ~data;
132 break;
133 case ASPEED_PCIE_RC_INT_STATUS: /* preserve INTx status*/
134 s->regs[TO_REG(addr)] &= ~data | ASPEED_PCIE_RC_INT_STATUS_INTX_MASK;
135 break;
136 default:
137 qemu_log_mask(LOG_GUEST_ERROR,
138 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
139 __func__, addr);
140 break;
141 }
142 }
143
144 static const MemoryRegionOps aspeed_pcie_rc_ops = {
145 .read = aspeed_pcie_rc_read,
146 .write = aspeed_pcie_rc_write,
147 .endianness = DEVICE_LITTLE_ENDIAN,
148 .valid = {
149 .min_access_size = 1,
150 .max_access_size = 4,
151 },
152 };
153
aspeed_pcie_rc_set_irq(void * opaque,int irq,int level)154 static void aspeed_pcie_rc_set_irq(void *opaque, int irq, int level)
155 {
156 AspeedPCIERc *s = (AspeedPCIERc *) opaque;
157
158 assert(irq < PCI_NUM_PINS);
159
160 if (level) {
161 s->regs[TO_REG(ASPEED_PCIE_RC_INT_STATUS)] |= BIT(irq);
162 } else {
163 s->regs[TO_REG(ASPEED_PCIE_RC_INT_STATUS)] &= ~BIT(irq);
164 }
165
166 aspeed_pcie_rc_update_irq(s);
167 }
168
aspeed_pcie_rc_map_irq(PCIDevice * pci_dev,int irq_num)169 static int aspeed_pcie_rc_map_irq(PCIDevice *pci_dev, int irq_num)
170 {
171 return irq_num % PCI_NUM_PINS;
172 }
173
aspeed_pcie_rc_realize(DeviceState * dev,Error ** errp)174 static void aspeed_pcie_rc_realize(DeviceState *dev, Error **errp)
175 {
176 PCIHostState *pci = PCI_HOST_BRIDGE(dev);
177 AspeedPCIERc *s = ASPEED_PCIE_RC(dev);
178 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
179 PCIExpressHost *pex = PCIE_HOST_BRIDGE(dev);
180
181 memory_region_init_io(&s->reg_rc_mmio, OBJECT(s), &aspeed_pcie_rc_ops, s,
182 TYPE_ASPEED_PCIE_RC ".regs", 0x40);
183
184 /* PCI configuration space */
185 pcie_host_mmcfg_init(pex, PCIE_MMCFG_SIZE_MAX / 2);
186 sysbus_init_mmio(sbd, &pex->mmio);
187
188 /* MMIO and IO region */
189 memory_region_init(&s->mmio, OBJECT(s), "mmio", UINT64_MAX);
190 memory_region_init(&s->io, OBJECT(s), "io", 0x10000);
191
192 memory_region_init_io(&s->mmio_window, OBJECT(s), &unassigned_io_ops,
193 OBJECT(s), "mmio_window", UINT64_MAX);
194 memory_region_init_io(&s->io_window, OBJECT(s), &unassigned_io_ops,
195 OBJECT(s), "ioport_window", 64 * 1024);
196
197 memory_region_add_subregion(&s->mmio_window, 0, &s->mmio);
198 memory_region_add_subregion(&s->io_window, 0, &s->io);
199 sysbus_init_mmio(sbd, &s->mmio_window);
200 sysbus_init_mmio(sbd, &s->io_window);
201
202 sysbus_init_irq(sbd, &s->irq);
203
204 pci->bus = pci_register_root_bus(dev, dev->id, aspeed_pcie_rc_set_irq,
205 aspeed_pcie_rc_map_irq, s, &s->mmio,
206 &s->io, 0, 4, TYPE_PCIE_BUS);
207 pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
208
209 qdev_realize(DEVICE(&s->root), BUS(pci->bus), &error_fatal);
210 }
211
aspeed_pcie_rc_reset(DeviceState * dev)212 static void aspeed_pcie_rc_reset(DeviceState *dev)
213 {
214 AspeedPCIERc *s = ASPEED_PCIE_RC(dev);
215
216 memset(s->regs, 0, sizeof(s->regs));
217 }
218
aspeed_pcie_rc_root_bus_path(PCIHostState * host_bridge,PCIBus * rootbus)219 static const char *aspeed_pcie_rc_root_bus_path(PCIHostState *host_bridge,
220 PCIBus *rootbus)
221 {
222 AspeedPCIERc *s = ASPEED_PCIE_RC(host_bridge);
223
224 snprintf(s->name, sizeof(s->name), "0000:%02x", s->bus_nr);
225 return s->name;
226 }
227
aspeed_pcie_rc_init(Object * obj)228 static void aspeed_pcie_rc_init(Object *obj)
229 {
230 AspeedPCIERc *s = ASPEED_PCIE_RC(obj);
231 AspeedPCIERoot *root = &s->root;
232
233 object_initialize_child(obj, "root", root, TYPE_ASPEED_PCIE_ROOT);
234 qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0));
235 qdev_prop_set_bit(DEVICE(root), "multifunction", false);
236 }
237
238 static const Property aspeed_pcie_rc_props[] = {
239 DEFINE_PROP_UINT32("bus-nr", AspeedPCIERc, bus_nr, 0),
240 };
241
aspeed_pcie_rc_class_init(ObjectClass * klass,void * data)242 static void aspeed_pcie_rc_class_init(ObjectClass *klass, void *data)
243 {
244 DeviceClass *dc = DEVICE_CLASS(klass);
245 PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
246
247 hc->root_bus_path = aspeed_pcie_rc_root_bus_path;
248 device_class_set_legacy_reset(dc, aspeed_pcie_rc_reset);
249 dc->realize = aspeed_pcie_rc_realize;
250 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
251 dc->fw_name = "pci";
252 device_class_set_props(dc, aspeed_pcie_rc_props);
253
254 msi_nonbroken = true;
255 }
256
257 static const TypeInfo aspeed_pcie_rc_info = {
258 .name = TYPE_ASPEED_PCIE_RC,
259 .parent = TYPE_PCIE_HOST_BRIDGE,
260 .instance_size = sizeof(AspeedPCIERc),
261 .instance_init = aspeed_pcie_rc_init,
262 .class_init = aspeed_pcie_rc_class_init,
263 };
264
aspeed_pcie_root_class_init(ObjectClass * klass,void * data)265 static void aspeed_pcie_root_class_init(ObjectClass *klass, void *data)
266 {
267 DeviceClass *dc = DEVICE_CLASS(klass);
268 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
269
270 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
271 dc->desc = "Aspeed PCIe Host Bridge";
272
273 k->vendor_id = PCI_VENDOR_ID_ASPEED;
274 k->device_id = PCI_DEVICE_ID_AST2600_RC;
275 k->revision = 0;
276 k->class_id = PCI_CLASS_BRIDGE_HOST;
277
278 /* */
279 dc->user_creatable = false;
280 }
281
282 static const TypeInfo aspeed_pcie_root_info = {
283 .name = TYPE_ASPEED_PCIE_ROOT,
284 .parent = TYPE_PCI_DEVICE,
285 .instance_size = sizeof(AspeedPCIERoot),
286 .class_init = aspeed_pcie_root_class_init,
287 .interfaces = (InterfaceInfo[]) {
288 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
289 { }
290 },
291 };
292
293 /*
294 * AHB to PCIe bridge (PCIECFG)
295 */
296
297 #define ASPEED_PCIE_CFG_CTRL 0x00
298 #define ASPEED_PCIE_CFG_CTRL_ENABLE BIT(0)
299 #define ASPEED_PCIE_CFG_CTRL_CLEAR_RX BIT(4)
300 #define ASPEED_PCIE_CFG_EN_IRQ 0x04
301 #define ASPEED_PCIE_CFG_TX_CLEAR 0x08
302 #define ASPEED_PCIE_CFG_RX_DATA 0x0C
303 #define ASPEED_PCIE_CFG_TX_DW0 0x10
304 #define ASPEED_PCIE_CFG_TX_DW1 0x14
305 #define ASPEED_PCIE_CFG_TX_DW2 0x18
306 #define ASPEED_PCIE_CFG_TX_DW3 0x1C
307 #define ASPEED_PCIE_CFG_TX_DATA 0x20
308 #define ASPEED_PCIE_CFG_TX_STATUS 0x24
309 #define ASPEED_PCIE_CFG_TX_STATUS_IDLE BIT(31)
310 #define ASPEED_PCIE_CFG_TX_STATUS_RC_H_RX_DONE BIT(27)
311 #define ASPEED_PCIE_CFG_TX_STATUS_RC_L_RX_DONE BIT(26)
312 #define ASPEED_PCIE_CFG_TX_STATUS_RC_H_TX_DONE BIT(25)
313 #define ASPEED_PCIE_CFG_TX_STATUS_RC_L_TX_DONE BIT(24)
314 #define ASPEED_PCIE_CFG_TX_STATUS_TRIG BIT(0)
315 #define ASPEED_PCIE_CFG_MSI0 0x58
316 #define ASPEED_PCIE_CFG_MSI1 0x5C
317 #define ASPEED_PCIE_CFG_REG60 0x60
318 #define ASPEED_PCIE_CFG_REG64 0x64
319 #define ASPEED_PCIE_CFG_REG68 0x68
320
321 #define ASPEED_PCIE_CFG_RC_MAX_MSI 64
322
aspeed_pcie_cfg_read(void * opaque,hwaddr addr,unsigned int size)323 static uint64_t aspeed_pcie_cfg_read(void *opaque, hwaddr addr,
324 unsigned int size)
325 {
326 AspeedPCIECfg *s = ASPEED_PCIE_CFG(opaque);
327 uint64_t val = 0;
328
329 switch (addr) {
330 case ASPEED_PCIE_CFG_CTRL:
331 case ASPEED_PCIE_CFG_EN_IRQ:
332 case ASPEED_PCIE_CFG_TX_CLEAR:
333 case ASPEED_PCIE_CFG_RX_DATA:
334 case ASPEED_PCIE_CFG_TX_DW0:
335 case ASPEED_PCIE_CFG_TX_DW1:
336 case ASPEED_PCIE_CFG_TX_DW2:
337 case ASPEED_PCIE_CFG_TX_DW3:
338 case ASPEED_PCIE_CFG_TX_STATUS:
339 case ASPEED_PCIE_CFG_REG60:
340 case ASPEED_PCIE_CFG_REG64:
341 case ASPEED_PCIE_CFG_REG68:
342 val = s->regs[TO_REG(addr)];
343 break;
344 case ASPEED_PCIE_CFG_MSI0:
345 case ASPEED_PCIE_CFG_MSI1:
346 printf("%s: 0x%" HWADDR_PRIx "\n", __func__, addr);
347 val = s->regs[TO_REG(addr)];
348 break;
349 default:
350 qemu_log_mask(LOG_GUEST_ERROR,
351 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
352 __func__, addr);
353 break;
354 }
355
356 trace_aspeed_pcie_cfg_read(addr, val);
357 return val;
358 }
359
360 #define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */
361 #define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */
362 #define TLP_FMTTYPE_CFGRD1 0x05 /* Configuration Read Type 1 */
363 #define TLP_FMTTYPE_CFGWR1 0x45 /* Configuration Write Type 1 */
364
365 #define PCIE_CFG_FMTTYPE_MASK(dw0) (((dw0) >> 24) & 0xff)
366 #define PCIE_CFG_BYTE_EN(dw1) ((dw1) & 0xf)
367
368 #define PCIE_MMCFG_ADDR(bus, devfn, offset) \
369 ((((bus) & PCIE_MMCFG_BUS_MASK) << PCIE_MMCFG_BUS_BIT) | \
370 (((devfn) & PCIE_MMCFG_DEVFN_MASK) << PCIE_MMCFG_DEVFN_BIT) | \
371 ((offset) & PCIE_MMCFG_CONFOFFSET_MASK))
372
373 /* TODO : find a better way to deduce len/addr/val from byte enable */
aspeed_pcie_cfg_translate_write(AspeedPCIECfg * s,uint32_t * addr,uint64_t * val,int * len)374 static void aspeed_pcie_cfg_translate_write(AspeedPCIECfg *s, uint32_t *addr,
375 uint64_t *val, int *len)
376 {
377 uint8_t byte_en = PCIE_CFG_BYTE_EN(s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW1)]);
378
379 *len = ctpop8(byte_en);
380
381 switch (byte_en) {
382 case 0x1:
383 case 0x3:
384 case 0xf:
385 break;
386 case 0x4:
387 *addr += 2;
388 *val = (*val >> (2 * 8)) & MAKE_64BIT_MASK(0, *len * 8);
389 break;
390 case 0x2:
391 case 0xc:
392 *addr += *len;
393 *val = (*val >> (*len * 8)) & MAKE_64BIT_MASK(0, *len * 8);
394 break;
395 default:
396 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid byte enable: %d\n",
397 __func__, byte_en);
398 g_assert_not_reached();
399 }
400 }
401
aspeed_pcie_cfg_readwrite(AspeedPCIECfg * s)402 static void aspeed_pcie_cfg_readwrite(AspeedPCIECfg *s)
403 {
404 bool is_write = !!(s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW0)] & (1ul << 30));
405 uint32_t cfg_addr = s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW2)];
406 uint8_t bus = (cfg_addr >> 24) & 0xff;
407 uint8_t devfn = (cfg_addr >> 16) & 0xff;
408 uint32_t offset = cfg_addr & 0xffc;
409 uint8_t rc_index = !!(bus & 0x80);
410 AspeedPCIERc *rc = &s->rcs[rc_index];
411
412 uint64_t val = ~0;
413 int len;
414
415 PCIHostState *pci = PCI_HOST_BRIDGE(rc);
416 PCIDevice *pdev;
417
418 /* HACK: rework host bridge */
419 if (bus == 0x80) {
420 bus = 0;
421 }
422
423 pdev = pci_find_device(pci->bus, bus, devfn);
424 if (!pdev) {
425 rc->regs[TO_REG(ASPEED_PCIE_RC_RX_DATA)] = ~0;
426 goto out;
427 }
428
429 switch (PCIE_CFG_FMTTYPE_MASK(s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW0)])) {
430 case TLP_FMTTYPE_CFGWR0:
431 case TLP_FMTTYPE_CFGWR1:
432 val = s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DATA)];
433 aspeed_pcie_cfg_translate_write(s, &offset, &val, &len);
434
435 pci_host_config_write_common(pdev, offset, pci_config_size(pdev),
436 val, len);
437 break;
438
439 case TLP_FMTTYPE_CFGRD0:
440 case TLP_FMTTYPE_CFGRD1:
441 val = pci_host_config_read_common(pdev, offset,
442 pci_config_size(pdev), 4);
443 rc->regs[TO_REG(ASPEED_PCIE_RC_RX_DATA)] = val;
444 break;
445 default:
446 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid CFG type. DW0=0x%x\n",
447 __func__, s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW0)]);
448 }
449
450 out:
451 rc->regs[TO_REG(ASPEED_PCIE_RC_INT_STATUS)] |=
452 ASPEED_PCIE_RC_INT_STATUS_RX;
453
454 s->regs[TO_REG(ASPEED_PCIE_CFG_TX_STATUS)] |= BIT(24 + rc_index);
455 s->regs[TO_REG(ASPEED_PCIE_CFG_TX_STATUS)] |=
456 ASPEED_PCIE_CFG_TX_STATUS_IDLE;
457
458 trace_aspeed_pcie_cfg_rw(is_write ? "write" : "read", bus, devfn,
459 cfg_addr, val);
460 }
461
aspeed_pcie_cfg_msi_notify(AspeedPCIECfg * s,hwaddr addr,uint64_t data)462 static void aspeed_pcie_cfg_msi_notify(AspeedPCIECfg *s, hwaddr addr,
463 uint64_t data)
464 {
465 bool rc_index = !!(addr == ASPEED_PCIE_CFG_MSI1);
466 AspeedPCIERc *rc = &s->rcs[rc_index];
467 int reg;
468
469 trace_aspeed_pcie_cfg_msi_notify(addr, data);
470
471 /* Written data is the HW IRQ number */
472 if (data >= ASPEED_PCIE_CFG_RC_MAX_MSI) {
473 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid MSI vector %"PRIx64"\n",
474 __func__, data);
475 return;
476 }
477
478 /* TODO: what is ASPEED_PCIE_RC_CTRL_RX_MSI_SELECT ? */
479 if (!(rc->regs[TO_REG(ASPEED_PCIE_RC_CTRL)] &
480 ASPEED_PCIE_RC_CTRL_RX_MSI)) {
481 qemu_log_mask(LOG_GUEST_ERROR, "%s: MSI are not enabled\n", __func__);
482 return;
483 }
484
485 reg = data < 32 ? ASPEED_PCIE_RC_MSI_STATUS0 : ASPEED_PCIE_RC_MSI_STATUS1;
486
487 rc->regs[TO_REG(reg)] |= BIT(data % 32);
488 aspeed_pcie_rc_update_irq(rc);
489 }
490
aspeed_pcie_cfg_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)491 static void aspeed_pcie_cfg_write(void *opaque, hwaddr addr, uint64_t data,
492 unsigned int size)
493 {
494 AspeedPCIECfg *s = ASPEED_PCIE_CFG(opaque);
495
496 trace_aspeed_pcie_cfg_write(addr, data);
497
498 /* TODO: test ASPEED_PCIE_CFG_CTRL_ENABLE */
499
500 switch (addr) {
501 case ASPEED_PCIE_CFG_EN_IRQ:
502 case ASPEED_PCIE_CFG_TX_DW0:
503 case ASPEED_PCIE_CFG_TX_DW1:
504 case ASPEED_PCIE_CFG_TX_DW2:
505 case ASPEED_PCIE_CFG_TX_DW3:
506 case ASPEED_PCIE_CFG_TX_DATA:
507 case ASPEED_PCIE_CFG_REG60:
508 case ASPEED_PCIE_CFG_REG64:
509 case ASPEED_PCIE_CFG_REG68:
510 s->regs[TO_REG(addr)] = data;
511 break;
512 case ASPEED_PCIE_CFG_MSI0:
513 case ASPEED_PCIE_CFG_MSI1:
514 aspeed_pcie_cfg_msi_notify(s, addr, data);
515 break;
516 case ASPEED_PCIE_CFG_CTRL:
517 if (data & ASPEED_PCIE_CFG_CTRL_CLEAR_RX) {
518 s->regs[TO_REG(ASPEED_PCIE_CFG_RX_DATA)] = ~0;
519 }
520 break;
521
522 case ASPEED_PCIE_CFG_TX_CLEAR:
523 if (data == 0x1) {
524 s->regs[TO_REG(ASPEED_PCIE_CFG_TX_STATUS)] &=
525 ~ASPEED_PCIE_CFG_TX_STATUS_IDLE;
526 }
527 break;
528 case ASPEED_PCIE_CFG_TX_STATUS:
529 if (data & ASPEED_PCIE_CFG_TX_STATUS_TRIG) {
530 aspeed_pcie_cfg_readwrite(s);
531 }
532 break;
533 default:
534 qemu_log_mask(LOG_GUEST_ERROR,
535 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
536 __func__, addr);
537 break;
538 }
539 }
540
541 static const MemoryRegionOps aspeed_pcie_cfg_ops = {
542 .read = aspeed_pcie_cfg_read,
543 .write = aspeed_pcie_cfg_write,
544 .endianness = DEVICE_LITTLE_ENDIAN,
545 .valid = {
546 .min_access_size = 1,
547 .max_access_size = 4,
548 },
549 };
550
aspeed_pcie_cfg_reset(DeviceState * dev)551 static void aspeed_pcie_cfg_reset(DeviceState *dev)
552 {
553 AspeedPCIECfg *s = ASPEED_PCIE_CFG(dev);
554
555 memset(s->regs, 0, sizeof(s->regs));
556 }
557
aspeed_pcie_cfg_instance_init(Object * obj)558 static void aspeed_pcie_cfg_instance_init(Object *obj)
559 {
560 AspeedPCIECfg *s = ASPEED_PCIE_CFG(obj);
561 int i;
562
563 for (i = 0; i < ARRAY_SIZE(s->rcs); i++) {
564 object_initialize_child(obj, "rcs[*]", &s->rcs[i],
565 TYPE_ASPEED_PCIE_RC);
566 }
567 }
568
aspeed_pcie_cfg_realize(DeviceState * dev,Error ** errp)569 static void aspeed_pcie_cfg_realize(DeviceState *dev, Error **errp)
570 {
571 AspeedPCIECfg *s = ASPEED_PCIE_CFG(dev);
572 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
573 int nr_rcs = ARRAY_SIZE(s->rcs);
574 int i;
575
576 memory_region_init(&s->reg_mmio_container, OBJECT(s),
577 TYPE_ASPEED_PCIE_CFG ".container", 0x100);
578 sysbus_init_mmio(sbd, &s->reg_mmio_container);
579
580 memory_region_init_io(&s->reg_cfg_mmio, OBJECT(s), &aspeed_pcie_cfg_ops, s,
581 TYPE_ASPEED_PCIE_CFG ".regs", 0x80);
582 memory_region_add_subregion(&s->reg_mmio_container, 0x0, &s->reg_cfg_mmio);
583
584 for (i = 0; i < nr_rcs; i++) {
585 object_property_set_int(OBJECT(&s->rcs[i]), "bus-nr",
586 i * PCI_BUS_MAX / nr_rcs, &error_abort);
587 if (!sysbus_realize(SYS_BUS_DEVICE(&s->rcs[i]), errp)) {
588 return;
589 }
590
591 /* RC registers */
592 memory_region_add_subregion(&s->reg_mmio_container, 0x80 + i * 0x40,
593 &s->rcs[i].reg_rc_mmio);
594 }
595 }
596
aspeed_pcie_cfg_class_init(ObjectClass * klass,void * data)597 static void aspeed_pcie_cfg_class_init(ObjectClass *klass, void *data)
598 {
599 DeviceClass *dc = DEVICE_CLASS(klass);
600
601 dc->realize = aspeed_pcie_cfg_realize;
602 device_class_set_legacy_reset(dc, aspeed_pcie_cfg_reset);
603 }
604
605 static const TypeInfo aspeed_pcie_cfg_info = {
606 .name = TYPE_ASPEED_PCIE_CFG,
607 .parent = TYPE_SYS_BUS_DEVICE,
608 .instance_size = sizeof(AspeedPCIECfg),
609 .instance_init = aspeed_pcie_cfg_instance_init,
610 .class_init = aspeed_pcie_cfg_class_init,
611 };
612
613
614 /*
615 * PHY
616 */
617
618 #define ASPEED_PCIE_PHY_DEVID 0x00
619 #define ASPEED_PCIE_PHY_CLASS_CODE 0x04
620 #define ASPEED_PCIE_PHY_CLASS_CODE_A3 0x6
621 #define ASPEED_PCIE_PHY_DATALINK 0x10
622 #define ASPEED_PCIE_PHY_HOTPLUG 0x14
623 #define ASPEED_PCIE_PHY_CTRL1 0x30
624 #define ASPEED_PCIE_PHY_CTRL1_ROOTPORT (BIT(5) | BIT(4))
625 #define ASPEED_PCIE_PHY_CTRL1_ENABLE BIT(1)
626 #define ASPEED_PCIE_PHY_PROTECT 0x7C
627 #define ASPEED_PCIE_PHY_LINK 0xC0
628 #define ASPEED_PCIE_PHY_LINK_STATUS BIT(5)
629 #define ASPEED_PCIE_PHY_BDF 0xC4
630 #define ASPEED_PCIE_PHY_LINK_STS 0xD0
631
aspeed_pcie_phy_read(void * opaque,hwaddr addr,unsigned int size)632 static uint64_t aspeed_pcie_phy_read(void *opaque, hwaddr addr,
633 unsigned int size)
634 {
635 AspeedPCIEPhy *s = ASPEED_PCIE_PHY(opaque);
636 uint64_t val = 0;
637
638 switch (addr) {
639 case ASPEED_PCIE_PHY_DEVID:
640 case ASPEED_PCIE_PHY_CLASS_CODE:
641 case ASPEED_PCIE_PHY_DATALINK:
642 case ASPEED_PCIE_PHY_CTRL1:
643 case ASPEED_PCIE_PHY_PROTECT:
644 case ASPEED_PCIE_PHY_LINK:
645 case ASPEED_PCIE_PHY_BDF:
646 case ASPEED_PCIE_PHY_LINK_STS:
647 val = s->regs[TO_REG(addr)];
648 break;
649 default:
650 qemu_log_mask(LOG_GUEST_ERROR,
651 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
652 __func__, addr);
653 break;
654 }
655
656 trace_aspeed_pcie_phy_read(addr, val);
657 return val;
658 }
659
aspeed_pcie_phy_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)660 static void aspeed_pcie_phy_write(void *opaque, hwaddr addr, uint64_t data,
661 unsigned int size)
662 {
663 AspeedPCIEPhy *s = ASPEED_PCIE_PHY(opaque);
664
665 trace_aspeed_pcie_phy_write(addr, data);
666
667 /* TODO: test protect */
668
669 switch (addr) {
670 case ASPEED_PCIE_PHY_PROTECT:
671 data &= 0xff;
672 s->regs[TO_REG(addr)] = !!(data == 0xA8);
673 break;
674
675 case ASPEED_PCIE_PHY_DEVID:
676 case ASPEED_PCIE_PHY_CLASS_CODE:
677 case ASPEED_PCIE_PHY_DATALINK:
678 case ASPEED_PCIE_PHY_CTRL1: /* 0x30 == root port, else bridge */
679 s->regs[TO_REG(addr)] = data;
680 break;
681 default:
682 qemu_log_mask(LOG_GUEST_ERROR,
683 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
684 __func__, addr);
685 break;
686 }
687 }
688
689 static const MemoryRegionOps aspeed_pcie_phy_ops = {
690 .read = aspeed_pcie_phy_read,
691 .write = aspeed_pcie_phy_write,
692 .endianness = DEVICE_LITTLE_ENDIAN,
693 .valid = {
694 .min_access_size = 1,
695 .max_access_size = 4,
696 },
697 };
698
aspeed_pcie_phy_reset(DeviceState * dev)699 static void aspeed_pcie_phy_reset(DeviceState *dev)
700 {
701 AspeedPCIEPhy *s = ASPEED_PCIE_PHY(dev);
702
703 memset(s->regs, 0, sizeof(s->regs));
704
705 s->regs[TO_REG(ASPEED_PCIE_PHY_DEVID)] =
706 (PCI_DEVICE_ID_AST2600_RC << 16) | PCI_VENDOR_ID_ASPEED;
707 s->regs[TO_REG(ASPEED_PCIE_PHY_CLASS_CODE)] =
708 0x06040000 | ASPEED_PCIE_PHY_CLASS_CODE_A3;
709 s->regs[TO_REG(ASPEED_PCIE_PHY_DATALINK)] = 0xD7040022;
710 s->regs[TO_REG(ASPEED_PCIE_PHY_LINK)] = ASPEED_PCIE_PHY_LINK_STATUS;
711 s->regs[TO_REG(ASPEED_PCIE_PHY_BDF)] = 0x0; /* TODO: BUS+DEV */
712 }
713
aspeed_pcie_phy_realize(DeviceState * dev,Error ** errp)714 static void aspeed_pcie_phy_realize(DeviceState *dev, Error **errp)
715 {
716 AspeedPCIEPhy *s = ASPEED_PCIE_PHY(dev);
717 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
718
719 memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_pcie_phy_ops, s,
720 TYPE_ASPEED_PCIE_PHY, 0x200);
721 sysbus_init_mmio(sbd, &s->mmio);
722 }
723
aspeed_pcie_phy_class_init(ObjectClass * klass,void * data)724 static void aspeed_pcie_phy_class_init(ObjectClass *klass, void *data)
725 {
726 DeviceClass *dc = DEVICE_CLASS(klass);
727
728 dc->realize = aspeed_pcie_phy_realize;
729 device_class_set_legacy_reset(dc, aspeed_pcie_phy_reset);
730 }
731
732 static const TypeInfo aspeed_pcie_phy_info = {
733 .name = TYPE_ASPEED_PCIE_PHY,
734 .parent = TYPE_SYS_BUS_DEVICE,
735 .instance_size = sizeof(AspeedPCIEPhy),
736 .class_init = aspeed_pcie_phy_class_init,
737 };
738
aspeed_pcie_register(void)739 static void aspeed_pcie_register(void)
740 {
741 type_register_static(&aspeed_pcie_root_info);
742 type_register_static(&aspeed_pcie_rc_info);
743 type_register_static(&aspeed_pcie_phy_info);
744 type_register_static(&aspeed_pcie_cfg_info);
745 }
746
747 type_init(aspeed_pcie_register)
748