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 Property aspeed_pcie_rc_props[] = {
239 DEFINE_PROP_UINT32("bus-nr", AspeedPCIERc, bus_nr, 0),
240 DEFINE_PROP_END_OF_LIST(),
241 };
242
aspeed_pcie_rc_class_init(ObjectClass * klass,void * data)243 static void aspeed_pcie_rc_class_init(ObjectClass *klass, void *data)
244 {
245 DeviceClass *dc = DEVICE_CLASS(klass);
246 PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
247
248 hc->root_bus_path = aspeed_pcie_rc_root_bus_path;
249 device_class_set_legacy_reset(dc, aspeed_pcie_rc_reset);
250 dc->realize = aspeed_pcie_rc_realize;
251 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
252 dc->fw_name = "pci";
253 device_class_set_props(dc, aspeed_pcie_rc_props);
254
255 msi_nonbroken = true;
256 }
257
258 static const TypeInfo aspeed_pcie_rc_info = {
259 .name = TYPE_ASPEED_PCIE_RC,
260 .parent = TYPE_PCIE_HOST_BRIDGE,
261 .instance_size = sizeof(AspeedPCIERc),
262 .instance_init = aspeed_pcie_rc_init,
263 .class_init = aspeed_pcie_rc_class_init,
264 };
265
aspeed_pcie_root_class_init(ObjectClass * klass,void * data)266 static void aspeed_pcie_root_class_init(ObjectClass *klass, void *data)
267 {
268 DeviceClass *dc = DEVICE_CLASS(klass);
269 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
270
271 set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
272 dc->desc = "Aspeed PCIe Host Bridge";
273
274 k->vendor_id = PCI_VENDOR_ID_ASPEED;
275 k->device_id = PCI_DEVICE_ID_AST2600_RC;
276 k->revision = 0;
277 k->class_id = PCI_CLASS_BRIDGE_HOST;
278
279 /* */
280 dc->user_creatable = false;
281 }
282
283 static const TypeInfo aspeed_pcie_root_info = {
284 .name = TYPE_ASPEED_PCIE_ROOT,
285 .parent = TYPE_PCI_DEVICE,
286 .instance_size = sizeof(AspeedPCIERoot),
287 .class_init = aspeed_pcie_root_class_init,
288 .interfaces = (InterfaceInfo[]) {
289 { INTERFACE_CONVENTIONAL_PCI_DEVICE },
290 { }
291 },
292 };
293
294 /*
295 * AHB to PCIe bridge (PCIECFG)
296 */
297
298 #define ASPEED_PCIE_CFG_CTRL 0x00
299 #define ASPEED_PCIE_CFG_CTRL_ENABLE BIT(0)
300 #define ASPEED_PCIE_CFG_CTRL_CLEAR_RX BIT(4)
301 #define ASPEED_PCIE_CFG_EN_IRQ 0x04
302 #define ASPEED_PCIE_CFG_TX_CLEAR 0x08
303 #define ASPEED_PCIE_CFG_RX_DATA 0x0C
304 #define ASPEED_PCIE_CFG_TX_DW0 0x10
305 #define ASPEED_PCIE_CFG_TX_DW1 0x14
306 #define ASPEED_PCIE_CFG_TX_DW2 0x18
307 #define ASPEED_PCIE_CFG_TX_DW3 0x1C
308 #define ASPEED_PCIE_CFG_TX_DATA 0x20
309 #define ASPEED_PCIE_CFG_TX_STATUS 0x24
310 #define ASPEED_PCIE_CFG_TX_STATUS_IDLE BIT(31)
311 #define ASPEED_PCIE_CFG_TX_STATUS_RC_H_RX_DONE BIT(27)
312 #define ASPEED_PCIE_CFG_TX_STATUS_RC_L_RX_DONE BIT(26)
313 #define ASPEED_PCIE_CFG_TX_STATUS_RC_H_TX_DONE BIT(25)
314 #define ASPEED_PCIE_CFG_TX_STATUS_RC_L_TX_DONE BIT(24)
315 #define ASPEED_PCIE_CFG_TX_STATUS_TRIG BIT(0)
316 #define ASPEED_PCIE_CFG_MSI0 0x58
317 #define ASPEED_PCIE_CFG_MSI1 0x5C
318 #define ASPEED_PCIE_CFG_REG60 0x60
319 #define ASPEED_PCIE_CFG_REG64 0x64
320 #define ASPEED_PCIE_CFG_REG68 0x68
321
322 #define ASPEED_PCIE_CFG_RC_MAX_MSI 64
323
aspeed_pcie_cfg_read(void * opaque,hwaddr addr,unsigned int size)324 static uint64_t aspeed_pcie_cfg_read(void *opaque, hwaddr addr,
325 unsigned int size)
326 {
327 AspeedPCIECfg *s = ASPEED_PCIE_CFG(opaque);
328 uint64_t val = 0;
329
330 switch (addr) {
331 case ASPEED_PCIE_CFG_CTRL:
332 case ASPEED_PCIE_CFG_EN_IRQ:
333 case ASPEED_PCIE_CFG_TX_CLEAR:
334 case ASPEED_PCIE_CFG_RX_DATA:
335 case ASPEED_PCIE_CFG_TX_DW0:
336 case ASPEED_PCIE_CFG_TX_DW1:
337 case ASPEED_PCIE_CFG_TX_DW2:
338 case ASPEED_PCIE_CFG_TX_DW3:
339 case ASPEED_PCIE_CFG_TX_STATUS:
340 case ASPEED_PCIE_CFG_REG60:
341 case ASPEED_PCIE_CFG_REG64:
342 case ASPEED_PCIE_CFG_REG68:
343 val = s->regs[TO_REG(addr)];
344 break;
345 case ASPEED_PCIE_CFG_MSI0:
346 case ASPEED_PCIE_CFG_MSI1:
347 printf("%s: 0x%" HWADDR_PRIx "\n", __func__, addr);
348 val = s->regs[TO_REG(addr)];
349 break;
350 default:
351 qemu_log_mask(LOG_GUEST_ERROR,
352 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
353 __func__, addr);
354 break;
355 }
356
357 trace_aspeed_pcie_cfg_read(addr, val);
358 return val;
359 }
360
361 #define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */
362 #define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */
363 #define TLP_FMTTYPE_CFGRD1 0x05 /* Configuration Read Type 1 */
364 #define TLP_FMTTYPE_CFGWR1 0x45 /* Configuration Write Type 1 */
365
366 #define PCIE_CFG_FMTTYPE_MASK(dw0) (((dw0) >> 24) & 0xff)
367 #define PCIE_CFG_BYTE_EN(dw1) ((dw1) & 0xf)
368
369 #define PCIE_MMCFG_ADDR(bus, devfn, offset) \
370 ((((bus) & PCIE_MMCFG_BUS_MASK) << PCIE_MMCFG_BUS_BIT) | \
371 (((devfn) & PCIE_MMCFG_DEVFN_MASK) << PCIE_MMCFG_DEVFN_BIT) | \
372 ((offset) & PCIE_MMCFG_CONFOFFSET_MASK))
373
374 /* 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)375 static void aspeed_pcie_cfg_translate_write(AspeedPCIECfg *s, uint32_t *addr,
376 uint64_t *val, int *len)
377 {
378 uint8_t byte_en = PCIE_CFG_BYTE_EN(s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW1)]);
379
380 *len = ctpop8(byte_en);
381
382 switch (byte_en) {
383 case 0x1:
384 case 0x3:
385 case 0xf:
386 break;
387 case 0x4:
388 *addr += 2;
389 *val = (*val >> (2 * 8)) & MAKE_64BIT_MASK(0, *len * 8);
390 break;
391 case 0x2:
392 case 0xc:
393 *addr += *len;
394 *val = (*val >> (*len * 8)) & MAKE_64BIT_MASK(0, *len * 8);
395 break;
396 default:
397 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid byte enable: %d\n",
398 __func__, byte_en);
399 g_assert_not_reached();
400 }
401 }
402
aspeed_pcie_cfg_readwrite(AspeedPCIECfg * s)403 static void aspeed_pcie_cfg_readwrite(AspeedPCIECfg *s)
404 {
405 bool is_write = !!(s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW0)] & (1ul << 30));
406 uint32_t cfg_addr = s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW2)];
407 uint8_t bus = (cfg_addr >> 24) & 0xff;
408 uint8_t devfn = (cfg_addr >> 16) & 0xff;
409 uint32_t offset = cfg_addr & 0xffc;
410 uint8_t rc_index = !!(bus & 0x80);
411 AspeedPCIERc *rc = &s->rcs[rc_index];
412
413 uint64_t val = ~0;
414 int len;
415
416 PCIHostState *pci = PCI_HOST_BRIDGE(rc);
417 PCIDevice *pdev;
418
419 /* HACK: rework host bridge */
420 if (bus == 0x80) {
421 bus = 0;
422 }
423
424 pdev = pci_find_device(pci->bus, bus, devfn);
425 if (!pdev) {
426 rc->regs[TO_REG(ASPEED_PCIE_RC_RX_DATA)] = ~0;
427 goto out;
428 }
429
430 switch (PCIE_CFG_FMTTYPE_MASK(s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW0)])) {
431 case TLP_FMTTYPE_CFGWR0:
432 case TLP_FMTTYPE_CFGWR1:
433 val = s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DATA)];
434 aspeed_pcie_cfg_translate_write(s, &offset, &val, &len);
435
436 pci_host_config_write_common(pdev, offset, pci_config_size(pdev),
437 val, len);
438 break;
439
440 case TLP_FMTTYPE_CFGRD0:
441 case TLP_FMTTYPE_CFGRD1:
442 val = pci_host_config_read_common(pdev, offset,
443 pci_config_size(pdev), 4);
444 rc->regs[TO_REG(ASPEED_PCIE_RC_RX_DATA)] = val;
445 break;
446 default:
447 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid CFG type. DW0=0x%x\n",
448 __func__, s->regs[TO_REG(ASPEED_PCIE_CFG_TX_DW0)]);
449 }
450
451 out:
452 rc->regs[TO_REG(ASPEED_PCIE_RC_INT_STATUS)] |=
453 ASPEED_PCIE_RC_INT_STATUS_RX;
454
455 s->regs[TO_REG(ASPEED_PCIE_CFG_TX_STATUS)] |= BIT(24 + rc_index);
456 s->regs[TO_REG(ASPEED_PCIE_CFG_TX_STATUS)] |=
457 ASPEED_PCIE_CFG_TX_STATUS_IDLE;
458
459 trace_aspeed_pcie_cfg_rw(is_write ? "write" : "read", bus, devfn,
460 cfg_addr, val);
461 }
462
aspeed_pcie_cfg_msi_notify(AspeedPCIECfg * s,hwaddr addr,uint64_t data)463 static void aspeed_pcie_cfg_msi_notify(AspeedPCIECfg *s, hwaddr addr,
464 uint64_t data)
465 {
466 bool rc_index = !!(addr == ASPEED_PCIE_CFG_MSI1);
467 AspeedPCIERc *rc = &s->rcs[rc_index];
468 int reg;
469
470 trace_aspeed_pcie_cfg_msi_notify(addr, data);
471
472 /* Written data is the HW IRQ number */
473 if (data >= ASPEED_PCIE_CFG_RC_MAX_MSI) {
474 qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid MSI vector %"PRIx64"\n",
475 __func__, data);
476 return;
477 }
478
479 /* TODO: what is ASPEED_PCIE_RC_CTRL_RX_MSI_SELECT ? */
480 if (!(rc->regs[TO_REG(ASPEED_PCIE_RC_CTRL)] &
481 ASPEED_PCIE_RC_CTRL_RX_MSI)) {
482 qemu_log_mask(LOG_GUEST_ERROR, "%s: MSI are not enabled\n", __func__);
483 return;
484 }
485
486 reg = data < 32 ? ASPEED_PCIE_RC_MSI_STATUS0 : ASPEED_PCIE_RC_MSI_STATUS1;
487
488 rc->regs[TO_REG(reg)] |= BIT(data % 32);
489 aspeed_pcie_rc_update_irq(rc);
490 }
491
aspeed_pcie_cfg_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)492 static void aspeed_pcie_cfg_write(void *opaque, hwaddr addr, uint64_t data,
493 unsigned int size)
494 {
495 AspeedPCIECfg *s = ASPEED_PCIE_CFG(opaque);
496
497 trace_aspeed_pcie_cfg_write(addr, data);
498
499 /* TODO: test ASPEED_PCIE_CFG_CTRL_ENABLE */
500
501 switch (addr) {
502 case ASPEED_PCIE_CFG_EN_IRQ:
503 case ASPEED_PCIE_CFG_TX_DW0:
504 case ASPEED_PCIE_CFG_TX_DW1:
505 case ASPEED_PCIE_CFG_TX_DW2:
506 case ASPEED_PCIE_CFG_TX_DW3:
507 case ASPEED_PCIE_CFG_TX_DATA:
508 case ASPEED_PCIE_CFG_REG60:
509 case ASPEED_PCIE_CFG_REG64:
510 case ASPEED_PCIE_CFG_REG68:
511 s->regs[TO_REG(addr)] = data;
512 break;
513 case ASPEED_PCIE_CFG_MSI0:
514 case ASPEED_PCIE_CFG_MSI1:
515 aspeed_pcie_cfg_msi_notify(s, addr, data);
516 break;
517 case ASPEED_PCIE_CFG_CTRL:
518 if (data & ASPEED_PCIE_CFG_CTRL_CLEAR_RX) {
519 s->regs[TO_REG(ASPEED_PCIE_CFG_RX_DATA)] = ~0;
520 }
521 break;
522
523 case ASPEED_PCIE_CFG_TX_CLEAR:
524 if (data == 0x1) {
525 s->regs[TO_REG(ASPEED_PCIE_CFG_TX_STATUS)] &=
526 ~ASPEED_PCIE_CFG_TX_STATUS_IDLE;
527 }
528 break;
529 case ASPEED_PCIE_CFG_TX_STATUS:
530 if (data & ASPEED_PCIE_CFG_TX_STATUS_TRIG) {
531 aspeed_pcie_cfg_readwrite(s);
532 }
533 break;
534 default:
535 qemu_log_mask(LOG_GUEST_ERROR,
536 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
537 __func__, addr);
538 break;
539 }
540 }
541
542 static const MemoryRegionOps aspeed_pcie_cfg_ops = {
543 .read = aspeed_pcie_cfg_read,
544 .write = aspeed_pcie_cfg_write,
545 .endianness = DEVICE_LITTLE_ENDIAN,
546 .valid = {
547 .min_access_size = 1,
548 .max_access_size = 4,
549 },
550 };
551
aspeed_pcie_cfg_reset(DeviceState * dev)552 static void aspeed_pcie_cfg_reset(DeviceState *dev)
553 {
554 AspeedPCIECfg *s = ASPEED_PCIE_CFG(dev);
555
556 memset(s->regs, 0, sizeof(s->regs));
557 }
558
aspeed_pcie_cfg_instance_init(Object * obj)559 static void aspeed_pcie_cfg_instance_init(Object *obj)
560 {
561 AspeedPCIECfg *s = ASPEED_PCIE_CFG(obj);
562 int i;
563
564 for (i = 0; i < ARRAY_SIZE(s->rcs); i++) {
565 object_initialize_child(obj, "rcs[*]", &s->rcs[i],
566 TYPE_ASPEED_PCIE_RC);
567 }
568 }
569
aspeed_pcie_cfg_realize(DeviceState * dev,Error ** errp)570 static void aspeed_pcie_cfg_realize(DeviceState *dev, Error **errp)
571 {
572 AspeedPCIECfg *s = ASPEED_PCIE_CFG(dev);
573 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
574 int nr_rcs = ARRAY_SIZE(s->rcs);
575 int i;
576
577 memory_region_init(&s->reg_mmio_container, OBJECT(s),
578 TYPE_ASPEED_PCIE_CFG ".container", 0x100);
579 sysbus_init_mmio(sbd, &s->reg_mmio_container);
580
581 memory_region_init_io(&s->reg_cfg_mmio, OBJECT(s), &aspeed_pcie_cfg_ops, s,
582 TYPE_ASPEED_PCIE_CFG ".regs", 0x80);
583 memory_region_add_subregion(&s->reg_mmio_container, 0x0, &s->reg_cfg_mmio);
584
585 for (i = 0; i < nr_rcs; i++) {
586 object_property_set_int(OBJECT(&s->rcs[i]), "bus-nr",
587 i * PCI_BUS_MAX / nr_rcs, &error_abort);
588 if (!sysbus_realize(SYS_BUS_DEVICE(&s->rcs[i]), errp)) {
589 return;
590 }
591
592 /* RC registers */
593 memory_region_add_subregion(&s->reg_mmio_container, 0x80 + i * 0x40,
594 &s->rcs[i].reg_rc_mmio);
595 }
596 }
597
598 static Property aspeed_pcie_cfg_props[] = {
599 DEFINE_PROP_END_OF_LIST(),
600 };
601
aspeed_pcie_cfg_class_init(ObjectClass * klass,void * data)602 static void aspeed_pcie_cfg_class_init(ObjectClass *klass, void *data)
603 {
604 DeviceClass *dc = DEVICE_CLASS(klass);
605
606 dc->realize = aspeed_pcie_cfg_realize;
607 device_class_set_legacy_reset(dc, aspeed_pcie_cfg_reset);
608 device_class_set_props(dc, aspeed_pcie_cfg_props);
609 }
610
611 static const TypeInfo aspeed_pcie_cfg_info = {
612 .name = TYPE_ASPEED_PCIE_CFG,
613 .parent = TYPE_SYS_BUS_DEVICE,
614 .instance_size = sizeof(AspeedPCIECfg),
615 .instance_init = aspeed_pcie_cfg_instance_init,
616 .class_init = aspeed_pcie_cfg_class_init,
617 };
618
619
620 /*
621 * PHY
622 */
623
624 #define ASPEED_PCIE_PHY_DEVID 0x00
625 #define ASPEED_PCIE_PHY_CLASS_CODE 0x04
626 #define ASPEED_PCIE_PHY_CLASS_CODE_A3 0x6
627 #define ASPEED_PCIE_PHY_DATALINK 0x10
628 #define ASPEED_PCIE_PHY_HOTPLUG 0x14
629 #define ASPEED_PCIE_PHY_CTRL1 0x30
630 #define ASPEED_PCIE_PHY_CTRL1_ROOTPORT (BIT(5) | BIT(4))
631 #define ASPEED_PCIE_PHY_CTRL1_ENABLE BIT(1)
632 #define ASPEED_PCIE_PHY_PROTECT 0x7C
633 #define ASPEED_PCIE_PHY_LINK 0xC0
634 #define ASPEED_PCIE_PHY_LINK_STATUS BIT(5)
635 #define ASPEED_PCIE_PHY_BDF 0xC4
636 #define ASPEED_PCIE_PHY_LINK_STS 0xD0
637
aspeed_pcie_phy_read(void * opaque,hwaddr addr,unsigned int size)638 static uint64_t aspeed_pcie_phy_read(void *opaque, hwaddr addr,
639 unsigned int size)
640 {
641 AspeedPCIEPhy *s = ASPEED_PCIE_PHY(opaque);
642 uint64_t val = 0;
643
644 switch (addr) {
645 case ASPEED_PCIE_PHY_DEVID:
646 case ASPEED_PCIE_PHY_CLASS_CODE:
647 case ASPEED_PCIE_PHY_DATALINK:
648 case ASPEED_PCIE_PHY_CTRL1:
649 case ASPEED_PCIE_PHY_PROTECT:
650 case ASPEED_PCIE_PHY_LINK:
651 case ASPEED_PCIE_PHY_BDF:
652 case ASPEED_PCIE_PHY_LINK_STS:
653 val = s->regs[TO_REG(addr)];
654 break;
655 default:
656 qemu_log_mask(LOG_GUEST_ERROR,
657 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
658 __func__, addr);
659 break;
660 }
661
662 trace_aspeed_pcie_phy_read(addr, val);
663 return val;
664 }
665
aspeed_pcie_phy_write(void * opaque,hwaddr addr,uint64_t data,unsigned int size)666 static void aspeed_pcie_phy_write(void *opaque, hwaddr addr, uint64_t data,
667 unsigned int size)
668 {
669 AspeedPCIEPhy *s = ASPEED_PCIE_PHY(opaque);
670
671 trace_aspeed_pcie_phy_write(addr, data);
672
673 /* TODO: test protect */
674
675 switch (addr) {
676 case ASPEED_PCIE_PHY_PROTECT:
677 data &= 0xff;
678 s->regs[TO_REG(addr)] = !!(data == 0xA8);
679 break;
680
681 case ASPEED_PCIE_PHY_DEVID:
682 case ASPEED_PCIE_PHY_CLASS_CODE:
683 case ASPEED_PCIE_PHY_DATALINK:
684 case ASPEED_PCIE_PHY_CTRL1: /* 0x30 == root port, else bridge */
685 s->regs[TO_REG(addr)] = data;
686 break;
687 default:
688 qemu_log_mask(LOG_GUEST_ERROR,
689 "%s: Out-of-bounds read at offset 0x%" HWADDR_PRIx "\n",
690 __func__, addr);
691 break;
692 }
693 }
694
695 static const MemoryRegionOps aspeed_pcie_phy_ops = {
696 .read = aspeed_pcie_phy_read,
697 .write = aspeed_pcie_phy_write,
698 .endianness = DEVICE_LITTLE_ENDIAN,
699 .valid = {
700 .min_access_size = 1,
701 .max_access_size = 4,
702 },
703 };
704
aspeed_pcie_phy_reset(DeviceState * dev)705 static void aspeed_pcie_phy_reset(DeviceState *dev)
706 {
707 AspeedPCIEPhy *s = ASPEED_PCIE_PHY(dev);
708
709 memset(s->regs, 0, sizeof(s->regs));
710
711 s->regs[TO_REG(ASPEED_PCIE_PHY_DEVID)] =
712 (PCI_DEVICE_ID_AST2600_RC << 16) | PCI_VENDOR_ID_ASPEED;
713 s->regs[TO_REG(ASPEED_PCIE_PHY_CLASS_CODE)] =
714 0x06040000 | ASPEED_PCIE_PHY_CLASS_CODE_A3;
715 s->regs[TO_REG(ASPEED_PCIE_PHY_DATALINK)] = 0xD7040022;
716 s->regs[TO_REG(ASPEED_PCIE_PHY_LINK)] = ASPEED_PCIE_PHY_LINK_STATUS;
717 s->regs[TO_REG(ASPEED_PCIE_PHY_BDF)] = 0x0; /* TODO: BUS+DEV */
718 }
719
aspeed_pcie_phy_realize(DeviceState * dev,Error ** errp)720 static void aspeed_pcie_phy_realize(DeviceState *dev, Error **errp)
721 {
722 AspeedPCIEPhy *s = ASPEED_PCIE_PHY(dev);
723 SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
724
725 memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_pcie_phy_ops, s,
726 TYPE_ASPEED_PCIE_PHY, 0x200);
727 sysbus_init_mmio(sbd, &s->mmio);
728 }
729
730 static Property aspeed_pcie_phy_props[] = {
731 DEFINE_PROP_END_OF_LIST(),
732 };
733
aspeed_pcie_phy_class_init(ObjectClass * klass,void * data)734 static void aspeed_pcie_phy_class_init(ObjectClass *klass, void *data)
735 {
736 DeviceClass *dc = DEVICE_CLASS(klass);
737
738 dc->realize = aspeed_pcie_phy_realize;
739 device_class_set_legacy_reset(dc, aspeed_pcie_phy_reset);
740 device_class_set_props(dc, aspeed_pcie_phy_props);
741 }
742
743 static const TypeInfo aspeed_pcie_phy_info = {
744 .name = TYPE_ASPEED_PCIE_PHY,
745 .parent = TYPE_SYS_BUS_DEVICE,
746 .instance_size = sizeof(AspeedPCIEPhy),
747 .class_init = aspeed_pcie_phy_class_init,
748 };
749
aspeed_pcie_register(void)750 static void aspeed_pcie_register(void)
751 {
752 type_register_static(&aspeed_pcie_root_info);
753 type_register_static(&aspeed_pcie_rc_info);
754 type_register_static(&aspeed_pcie_phy_info);
755 type_register_static(&aspeed_pcie_cfg_info);
756 }
757
758 type_init(aspeed_pcie_register)
759