xref: /openbmc/qemu/hw/pci-host/aspeed_pcie.c (revision c0c20b214069a95663713fcb8af02b53a6c3d9ce)
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