xref: /openbmc/qemu/hw/pci-host/aspeed_pcie.c (revision d3920d9fb1f91d6e53dfeda590a9eea518def14e)
1 /*
2  * ASPEED PCIe Host Controller
3  *
4  * Copyright (C) 2025 ASPEED Technology Inc.
5  * Copyright (c) 2022 Cédric Le Goater <clg@kaod.org>
6  *
7  * Jamin Lin <jamin_lin@aspeedtech.com>
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  *
11  * This file is based on Cédric Le Goater's patch:
12  * "pci: Add Aspeed host bridge (WIP)"
13  * https://github.com/legoater/qemu/commit/d1b97b0c7844219d847122410dc189854f9d26df
14  *
15  * Modifications have been made to support the Aspeed AST2600 and AST2700
16  * platforms.
17  */
18 
19 #include "qemu/osdep.h"
20 #include "qemu/log.h"
21 #include "qapi/error.h"
22 #include "hw/qdev-properties.h"
23 #include "hw/registerfields.h"
24 #include "hw/irq.h"
25 #include "hw/pci/pci_host.h"
26 #include "hw/pci-host/aspeed_pcie.h"
27 #include "hw/pci/msi.h"
28 #include "trace.h"
29 
30 /*
31  * PCIe Root
32  */
33 
34 static void aspeed_pcie_root_class_init(ObjectClass *klass, const void *data)
35 {
36     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
37     DeviceClass *dc = DEVICE_CLASS(klass);
38 
39     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
40     dc->desc = "ASPEED PCIe Host Bridge";
41     k->vendor_id = PCI_VENDOR_ID_ASPEED;
42     k->device_id = 0x1150;
43     k->class_id = PCI_CLASS_BRIDGE_HOST;
44     k->revision = 0;
45 
46     /*
47      * PCI-facing part of the host bridge,
48      * not usable without the host-facing part
49      */
50     dc->user_creatable = false;
51 }
52 
53 static const TypeInfo aspeed_pcie_root_info = {
54     .name = TYPE_ASPEED_PCIE_ROOT,
55     .parent = TYPE_PCI_DEVICE,
56     .instance_size = sizeof(AspeedPCIERootState),
57     .class_init = aspeed_pcie_root_class_init,
58     .interfaces = (const InterfaceInfo[]) {
59         { INTERFACE_CONVENTIONAL_PCI_DEVICE },
60         { },
61     },
62 };
63 
64 /*
65  * PCIe Root Complex (RC)
66  */
67 
68 #define ASPEED_PCIE_CFG_RC_MAX_MSI 64
69 
70 static void aspeed_pcie_rc_set_irq(void *opaque, int irq, int level)
71 {
72     AspeedPCIERcState *rc = (AspeedPCIERcState *) opaque;
73     AspeedPCIECfgState *cfg =
74         container_of(rc, AspeedPCIECfgState, rc);
75     AspeedPCIECfgClass *apc = ASPEED_PCIE_CFG_GET_CLASS(cfg);
76     const AspeedPCIERcRegs *rc_regs;
77     bool intx;
78 
79     assert(irq < PCI_NUM_PINS);
80 
81     rc_regs = &apc->reg_map->rc;
82 
83     if (level) {
84         cfg->regs[rc_regs->int_sts_reg] |= BIT(irq);
85     } else {
86         cfg->regs[rc_regs->int_sts_reg] &= ~BIT(irq);
87     }
88 
89     intx = !!(cfg->regs[rc_regs->int_sts_reg] & cfg->regs[rc_regs->int_en_reg]);
90     trace_aspeed_pcie_rc_intx_set_irq(cfg->id, irq, intx);
91     qemu_set_irq(rc->irq, intx);
92 }
93 
94 static int aspeed_pcie_rc_map_irq(PCIDevice *pci_dev, int irq_num)
95 {
96     return irq_num % PCI_NUM_PINS;
97 }
98 
99 static void aspeed_pcie_rc_msi_notify(AspeedPCIERcState *rc, uint64_t data)
100 {
101     AspeedPCIECfgState *cfg =
102            container_of(rc, AspeedPCIECfgState, rc);
103     AspeedPCIECfgClass *apc = ASPEED_PCIE_CFG_GET_CLASS(cfg);
104     const AspeedPCIERcRegs *rc_regs;
105     uint32_t reg;
106 
107     /* Written data is the HW IRQ number */
108     assert(data < ASPEED_PCIE_CFG_RC_MAX_MSI);
109 
110     rc_regs = &apc->reg_map->rc;
111 
112     reg = (data < 32) ? rc_regs->msi_sts0_reg : rc_regs->msi_sts1_reg;
113     cfg->regs[reg] |= BIT(data % 32);
114 
115     trace_aspeed_pcie_rc_msi_set_irq(cfg->id, data, 1);
116     qemu_set_irq(rc->irq, 1);
117 }
118 
119 static void aspeed_pcie_rc_msi_write(void *opaque, hwaddr addr, uint64_t data,
120                                      unsigned int size)
121 {
122     AspeedPCIERcState *rc = ASPEED_PCIE_RC(opaque);
123     AspeedPCIECfgState *cfg =
124            container_of(rc, AspeedPCIECfgState, rc);
125 
126     trace_aspeed_pcie_rc_msi_notify(cfg->id, addr + rc->msi_addr, data);
127     aspeed_pcie_rc_msi_notify(rc, data);
128 }
129 
130 static const MemoryRegionOps aspeed_pcie_rc_msi_ops = {
131     .write = aspeed_pcie_rc_msi_write,
132     .read = NULL,
133     .endianness = DEVICE_LITTLE_ENDIAN,
134     .valid = {
135         .min_access_size = 4,
136         .max_access_size = 4,
137     },
138     .impl = {
139         .min_access_size = 4,
140         .max_access_size = 4,
141     },
142 };
143 
144 static AddressSpace *aspeed_pcie_rc_get_as(PCIBus *bus, void *opaque, int devfn)
145 {
146     AspeedPCIERcState *rc = ASPEED_PCIE_RC(opaque);
147     return &rc->iommu_as;
148 }
149 
150 static const PCIIOMMUOps aspeed_pcie_rc_iommu_ops = {
151     .get_address_space = aspeed_pcie_rc_get_as,
152 };
153 
154 static void aspeed_pcie_rc_realize(DeviceState *dev, Error **errp)
155 {
156     PCIExpressHost *pex = PCIE_HOST_BRIDGE(dev);
157     AspeedPCIERcState *rc = ASPEED_PCIE_RC(dev);
158     AspeedPCIECfgState *cfg =
159            container_of(rc, AspeedPCIECfgState, rc);
160     PCIHostState *pci = PCI_HOST_BRIDGE(dev);
161     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
162     g_autofree char *name;
163 
164     /* PCI configuration space */
165     pcie_host_mmcfg_init(pex, PCIE_MMCFG_SIZE_MAX);
166     sysbus_init_mmio(sbd, &pex->mmio);
167 
168     /* MMIO and IO region */
169     memory_region_init(&rc->mmio, OBJECT(rc), "mmio", UINT64_MAX);
170     memory_region_init(&rc->io, OBJECT(rc), "io", 0x10000);
171 
172     name = g_strdup_printf("pcie.%d.mmio_window", cfg->id);
173     memory_region_init_io(&rc->mmio_window, OBJECT(rc), &unassigned_io_ops,
174                           OBJECT(rc), name, UINT64_MAX);
175     name = g_strdup_printf("pcie.%d.ioport_window", cfg->id);
176     memory_region_init_io(&rc->io_window, OBJECT(rc), &unassigned_io_ops,
177                           OBJECT(rc), name, 0x10000);
178 
179     memory_region_add_subregion(&rc->mmio_window, 0, &rc->mmio);
180     memory_region_add_subregion(&rc->io_window, 0, &rc->io);
181     sysbus_init_mmio(sbd, &rc->mmio_window);
182     sysbus_init_mmio(sbd, &rc->io_window);
183 
184     sysbus_init_irq(sbd, &rc->irq);
185     pci->bus = pci_register_root_bus(dev, NULL, aspeed_pcie_rc_set_irq,
186                                      aspeed_pcie_rc_map_irq, rc, &rc->mmio,
187                                      &rc->io, 0, 4, TYPE_PCIE_BUS);
188     pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
189 
190    /*
191     * PCIe memory view setup
192     *
193     * Background:
194     * - On AST2700, all Root Complexes use the same MSI address. This MSI
195     *   address is not normal system RAM - it is a PCI system memory address.
196     *   If we map the MSI/MSI-X window into real system memory, a write from
197     *   one EP can be seen by all RCs and wrongly trigger interrupts on them.
198     *
199     * Design:
200     * - MSI/MSI-X here is just a placeholder address so RC and EP can talk.
201     *   We make a separate MMIO space (iommu_root) for the MSI window so the
202     *   writes stay local to each RC.
203     *
204     * DMA:
205     * - EPs still need access to real system memory for DMA. We add a DRAM
206     *   alias in the PCI space so DMA works as expected.
207     */
208     name = g_strdup_printf("pcie.%d.iommu_root", cfg->id);
209     memory_region_init(&rc->iommu_root, OBJECT(rc), name, UINT64_MAX);
210     address_space_init(&rc->iommu_as, &rc->iommu_root, name);
211     /* setup MSI */
212     memory_region_init_io(&rc->msi_window, OBJECT(rc),
213                           &aspeed_pcie_rc_msi_ops, rc,
214                           "msi_window", 4);
215     memory_region_add_subregion(&rc->iommu_root, rc->msi_addr,
216                                 &rc->msi_window);
217     /* setup DRAM for DMA */
218     assert(rc->dram_mr != NULL);
219     name = g_strdup_printf("pcie.%d.dram_alias", cfg->id);
220     memory_region_init_alias(&rc->dram_alias, OBJECT(rc), name, rc->dram_mr,
221                              0, memory_region_size(rc->dram_mr));
222     memory_region_add_subregion(&rc->iommu_root, rc->dram_base,
223                                 &rc->dram_alias);
224     pci_setup_iommu(pci->bus, &aspeed_pcie_rc_iommu_ops, rc);
225 
226     qdev_realize(DEVICE(&rc->root), BUS(pci->bus), &error_fatal);
227 }
228 
229 static const char *aspeed_pcie_rc_root_bus_path(PCIHostState *host_bridge,
230                                                 PCIBus *rootbus)
231 {
232     AspeedPCIERcState *s = ASPEED_PCIE_RC(host_bridge);
233 
234     snprintf(s->name, sizeof(s->name), "0000:%02x", s->bus_nr);
235 
236     return s->name;
237 }
238 
239 static void aspeed_pcie_rc_instance_init(Object *obj)
240 {
241     AspeedPCIERcState *s = ASPEED_PCIE_RC(obj);
242     AspeedPCIERootState *root = &s->root;
243 
244     object_initialize_child(obj, "root", root, TYPE_ASPEED_PCIE_ROOT);
245     qdev_prop_set_int32(DEVICE(root), "addr", PCI_DEVFN(0, 0));
246     qdev_prop_set_bit(DEVICE(root), "multifunction", false);
247 }
248 
249 static const Property aspeed_pcie_rc_props[] = {
250     DEFINE_PROP_UINT32("bus-nr", AspeedPCIERcState, bus_nr, 0),
251     DEFINE_PROP_UINT32("msi-addr", AspeedPCIERcState, msi_addr, 0),
252     DEFINE_PROP_UINT64("dram-base", AspeedPCIERcState, dram_base, 0),
253     DEFINE_PROP_LINK("dram", AspeedPCIERcState, dram_mr, TYPE_MEMORY_REGION,
254                      MemoryRegion *),
255 };
256 
257 static void aspeed_pcie_rc_class_init(ObjectClass *klass, const void *data)
258 {
259     PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass);
260     DeviceClass *dc = DEVICE_CLASS(klass);
261 
262     dc->desc = "ASPEED PCIe RC";
263     dc->realize = aspeed_pcie_rc_realize;
264     dc->fw_name = "pci";
265     set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
266 
267     hc->root_bus_path = aspeed_pcie_rc_root_bus_path;
268     device_class_set_props(dc, aspeed_pcie_rc_props);
269 
270     msi_nonbroken = true;
271 }
272 
273 static const TypeInfo aspeed_pcie_rc_info = {
274     .name = TYPE_ASPEED_PCIE_RC,
275     .parent = TYPE_PCIE_HOST_BRIDGE,
276     .instance_size = sizeof(AspeedPCIERcState),
277     .instance_init = aspeed_pcie_rc_instance_init,
278     .class_init = aspeed_pcie_rc_class_init,
279 };
280 
281 /*
282  * PCIe Config
283  *
284  * AHB to PCIe Bus Bridge (H2X)
285  *
286  * On the AST2600:
287  * NOTE: rc_l is not supported by this model.
288  * - Registers 0x00 - 0x7F are shared by both PCIe0 (rc_l) and PCIe1 (rc_h).
289  * - Registers 0x80 - 0xBF are specific to PCIe0.
290  * - Registers 0xC0 - 0xFF are specific to PCIe1.
291  */
292 
293 /* AST2600 */
294 REG32(H2X_CTRL,             0x00)
295     FIELD(H2X_CTRL, CLEAR_RX, 4, 1)
296 REG32(H2X_TX_CLEAR,         0x08)
297     FIELD(H2X_TX_CLEAR, IDLE, 0, 1)
298 REG32(H2X_RDATA,            0x0C)
299 REG32(H2X_TX_DESC0,         0x10)
300 REG32(H2X_TX_DESC1,         0x14)
301 REG32(H2X_TX_DESC2,         0x18)
302 REG32(H2X_TX_DESC3,         0x1C)
303 REG32(H2X_TX_DATA,          0x20)
304 REG32(H2X_TX_STS,           0x24)
305     FIELD(H2X_TX_STS, IDLE, 31, 1)
306     FIELD(H2X_TX_STS, RC_L_TX_COMP, 24, 1)
307     FIELD(H2X_TX_STS, RC_H_TX_COMP, 25, 1)
308     FIELD(H2X_TX_STS, TRIG, 0, 1)
309 REG32(H2X_RC_H_CTRL,        0xC0)
310 REG32(H2X_RC_H_INT_EN,      0xC4)
311 REG32(H2X_RC_H_INT_STS,     0xC8)
312     SHARED_FIELD(H2X_RC_INT_INTDONE, 4, 1)
313     SHARED_FIELD(H2X_RC_INT_INTX, 0, 4)
314 REG32(H2X_RC_H_RDATA,       0xCC)
315 REG32(H2X_RC_H_MSI_EN0,     0xE0)
316 REG32(H2X_RC_H_MSI_EN1,     0xE4)
317 REG32(H2X_RC_H_MSI_STS0,    0xE8)
318 REG32(H2X_RC_H_MSI_STS1,    0xEC)
319 
320 #define TLP_FMTTYPE_CFGRD0  0x04 /* Configuration Read  Type 0 */
321 #define TLP_FMTTYPE_CFGWR0  0x44 /* Configuration Write Type 0 */
322 #define TLP_FMTTYPE_CFGRD1  0x05 /* Configuration Read  Type 1 */
323 #define TLP_FMTTYPE_CFGWR1  0x45 /* Configuration Write Type 1 */
324 
325 #define PCIE_CFG_FMTTYPE_MASK(x) (((x) >> 24) & 0xff)
326 #define PCIE_CFG_BYTE_EN(x) ((x) & 0xf)
327 
328 static const AspeedPCIERegMap aspeed_regmap = {
329     .rc = {
330         .int_en_reg     = R_H2X_RC_H_INT_EN,
331         .int_sts_reg    = R_H2X_RC_H_INT_STS,
332         .msi_sts0_reg   = R_H2X_RC_H_MSI_STS0,
333         .msi_sts1_reg   = R_H2X_RC_H_MSI_STS1,
334     },
335 };
336 
337 static uint64_t aspeed_pcie_cfg_read(void *opaque, hwaddr addr,
338                                      unsigned int size)
339 {
340     AspeedPCIECfgState *s = ASPEED_PCIE_CFG(opaque);
341     uint32_t reg = addr >> 2;
342     uint32_t value = 0;
343 
344     value = s->regs[reg];
345 
346     trace_aspeed_pcie_cfg_read(s->id, addr, value);
347 
348     return value;
349 }
350 
351 static void aspeed_pcie_cfg_translate_write(uint8_t byte_en, uint32_t *addr,
352                                             uint64_t *val, int *len)
353 {
354     uint64_t packed_val = 0;
355     int first_bit = -1;
356     int index = 0;
357     int i;
358 
359     *len = ctpop8(byte_en);
360 
361     if (*len == 0 || *len > 4) {
362         goto err;
363     }
364 
365     /* Special case: full 4-byte write must be 4-byte aligned */
366     if (byte_en == 0x0f) {
367         if (*addr % 4 != 0) {
368             goto err;
369         }
370         *val = *val & 0xffffffff;
371         return;
372     }
373 
374     for (i = 0; i < 4; i++) {
375         if (byte_en & (1 << i)) {
376             if (first_bit < 0) {
377                 first_bit = i;
378             }
379             packed_val |= ((*val >> (i * 8)) & 0xff) << (index * 8);
380             index++;
381         }
382     }
383 
384     *addr += first_bit;
385     *val = packed_val;
386 
387     return;
388 
389 err:
390     qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid byte enable: 0x%x\n",
391                   __func__, byte_en);
392 }
393 
394 static void aspeed_pcie_cfg_readwrite(AspeedPCIECfgState *s,
395                                       const AspeedPCIECfgTxDesc *desc)
396 {
397     AspeedPCIERcState *rc = &s->rc;
398     PCIHostState *pci;
399     uint32_t cfg_addr;
400     PCIDevice *pdev;
401     uint32_t offset;
402     uint8_t byte_en;
403     bool is_write;
404     uint8_t devfn;
405     uint64_t val;
406     uint8_t bus;
407     int len;
408 
409     val = ~0;
410     is_write = !!(desc->desc0 & BIT(30));
411     cfg_addr = desc->desc2;
412 
413     bus = (cfg_addr >> 24) & 0xff;
414     devfn  = (cfg_addr >> 16) & 0xff;
415     offset = cfg_addr & 0xffc;
416 
417     pci = PCI_HOST_BRIDGE(rc);
418 
419     /*
420      * On the AST2600, the RC_H bus number ranges from 0x80 to 0xFF, and its
421      * root port uses bus number 0x80 instead of the standard 0x00. To locate
422      * the device at root port 0, remap bus number 0x80 to 0x00 so that the
423      * PCI subsystem can correctly discover the devices.
424      */
425     if (bus == rc->bus_nr) {
426         bus = 0;
427     }
428 
429     pdev = pci_find_device(pci->bus, bus, devfn);
430     if (!pdev) {
431         s->regs[desc->rdata_reg] = ~0;
432         goto out;
433     }
434 
435     switch (PCIE_CFG_FMTTYPE_MASK(desc->desc0)) {
436     case TLP_FMTTYPE_CFGWR0:
437     case TLP_FMTTYPE_CFGWR1:
438         byte_en = PCIE_CFG_BYTE_EN(desc->desc1);
439         val = desc->wdata;
440         aspeed_pcie_cfg_translate_write(byte_en, &offset, &val, &len);
441         pci_host_config_write_common(pdev, offset, pci_config_size(pdev),
442                                      val, len);
443         break;
444     case TLP_FMTTYPE_CFGRD0:
445     case TLP_FMTTYPE_CFGRD1:
446         val = pci_host_config_read_common(pdev, offset,
447                                           pci_config_size(pdev), 4);
448         s->regs[desc->rdata_reg] = val;
449         break;
450     default:
451         qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid CFG type. DESC0=0x%x\n",
452                       __func__, desc->desc0);
453     }
454 
455 out:
456     trace_aspeed_pcie_cfg_rw(s->id, is_write ?  "write" : "read", bus, devfn,
457                              cfg_addr, val);
458 }
459 
460 static void aspeed_pcie_cfg_write(void *opaque, hwaddr addr, uint64_t data,
461                                   unsigned int size)
462 {
463     AspeedPCIECfgState *s = ASPEED_PCIE_CFG(opaque);
464     AspeedPCIECfgClass *apc = ASPEED_PCIE_CFG_GET_CLASS(s);
465     AspeedPCIECfgTxDesc desc;
466     uint32_t reg = addr >> 2;
467     uint32_t rc_reg;
468 
469     trace_aspeed_pcie_cfg_write(s->id, addr, data);
470 
471     switch (reg) {
472     case R_H2X_CTRL:
473         if (data & R_H2X_CTRL_CLEAR_RX_MASK) {
474             s->regs[R_H2X_RDATA] = ~0;
475         }
476         break;
477     case R_H2X_TX_CLEAR:
478         if (data & R_H2X_TX_CLEAR_IDLE_MASK) {
479             s->regs[R_H2X_TX_STS] &= ~R_H2X_TX_STS_IDLE_MASK;
480         }
481         break;
482     case R_H2X_TX_STS:
483         if (data & R_H2X_TX_STS_TRIG_MASK) {
484             desc.desc0 = s->regs[R_H2X_TX_DESC0];
485             desc.desc1 = s->regs[R_H2X_TX_DESC1];
486             desc.desc2 = s->regs[R_H2X_TX_DESC2];
487             desc.desc3 = s->regs[R_H2X_TX_DESC3];
488             desc.wdata = s->regs[R_H2X_TX_DATA];
489             desc.rdata_reg = R_H2X_RC_H_RDATA;
490             aspeed_pcie_cfg_readwrite(s, &desc);
491             rc_reg = apc->reg_map->rc.int_sts_reg;
492             s->regs[rc_reg] |= H2X_RC_INT_INTDONE_MASK;
493             s->regs[R_H2X_TX_STS] |=
494                 BIT(R_H2X_TX_STS_RC_H_TX_COMP_SHIFT);
495             s->regs[R_H2X_TX_STS] |= R_H2X_TX_STS_IDLE_MASK;
496         }
497         break;
498     /* preserve INTx status */
499     case R_H2X_RC_H_INT_STS:
500         if (data & H2X_RC_INT_INTDONE_MASK) {
501             s->regs[R_H2X_TX_STS] &= ~R_H2X_TX_STS_RC_H_TX_COMP_MASK;
502         }
503         s->regs[reg] &= ~data | H2X_RC_INT_INTX_MASK;
504         break;
505     /*
506      * These status registers are used for notify sources ISR are executed.
507      * If one source ISR is executed, it will clear one bit.
508      * If it clear all bits, it means to initialize this register status
509      * rather than sources ISR are executed.
510      */
511     case R_H2X_RC_H_MSI_STS0:
512     case R_H2X_RC_H_MSI_STS1:
513         if (data == 0) {
514             return ;
515         }
516 
517         s->regs[reg] &= ~data;
518         if (data == 0xffffffff) {
519             return;
520         }
521 
522         if (!s->regs[R_H2X_RC_H_MSI_STS0] &&
523             !s->regs[R_H2X_RC_H_MSI_STS1]) {
524             trace_aspeed_pcie_rc_msi_clear_irq(s->id, 0);
525             qemu_set_irq(s->rc.irq, 0);
526         }
527         break;
528     default:
529         s->regs[reg] = data;
530         break;
531     }
532 }
533 
534 static const MemoryRegionOps aspeed_pcie_cfg_ops = {
535     .read = aspeed_pcie_cfg_read,
536     .write = aspeed_pcie_cfg_write,
537     .endianness = DEVICE_LITTLE_ENDIAN,
538     .valid = {
539         .min_access_size = 1,
540         .max_access_size = 4,
541     },
542 };
543 
544 static void aspeed_pcie_cfg_instance_init(Object *obj)
545 {
546     AspeedPCIECfgState *s = ASPEED_PCIE_CFG(obj);
547 
548     object_initialize_child(obj, "rc", &s->rc, TYPE_ASPEED_PCIE_RC);
549     object_property_add_alias(obj, "dram", OBJECT(&s->rc), "dram");
550     object_property_add_alias(obj, "dram-base", OBJECT(&s->rc), "dram-base");
551 
552     return;
553 }
554 
555 static void aspeed_pcie_cfg_reset(DeviceState *dev)
556 {
557     AspeedPCIECfgState *s = ASPEED_PCIE_CFG(dev);
558     AspeedPCIECfgClass *apc = ASPEED_PCIE_CFG_GET_CLASS(s);
559 
560     memset(s->regs, 0, apc->nr_regs << 2);
561 }
562 
563 static void aspeed_pcie_cfg_realize(DeviceState *dev, Error **errp)
564 {
565     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
566     AspeedPCIECfgState *s = ASPEED_PCIE_CFG(dev);
567     AspeedPCIECfgClass *apc = ASPEED_PCIE_CFG_GET_CLASS(s);
568     g_autofree char *name;
569 
570     s->regs = g_new(uint32_t, apc->nr_regs);
571     name = g_strdup_printf(TYPE_ASPEED_PCIE_CFG ".regs.%d", s->id);
572     memory_region_init_io(&s->mmio, OBJECT(s), apc->reg_ops, s, name,
573                           apc->nr_regs << 2);
574     sysbus_init_mmio(sbd, &s->mmio);
575 
576     object_property_set_int(OBJECT(&s->rc), "bus-nr",
577                             apc->rc_bus_nr,
578                             &error_abort);
579     object_property_set_int(OBJECT(&s->rc), "msi-addr",
580                             apc->rc_msi_addr,
581                             &error_abort);
582     if (!sysbus_realize(SYS_BUS_DEVICE(&s->rc), errp)) {
583         return;
584     }
585 }
586 
587 static void aspeed_pcie_cfg_unrealize(DeviceState *dev)
588 {
589     AspeedPCIECfgState *s = ASPEED_PCIE_CFG(dev);
590 
591     g_free(s->regs);
592     s->regs = NULL;
593 }
594 
595 static const Property aspeed_pcie_cfg_props[] = {
596     DEFINE_PROP_UINT32("id", AspeedPCIECfgState, id, 0),
597 };
598 
599 static void aspeed_pcie_cfg_class_init(ObjectClass *klass, const void *data)
600 {
601     DeviceClass *dc = DEVICE_CLASS(klass);
602     AspeedPCIECfgClass *apc = ASPEED_PCIE_CFG_CLASS(klass);
603 
604     dc->desc = "ASPEED PCIe Config";
605     dc->realize = aspeed_pcie_cfg_realize;
606     dc->unrealize = aspeed_pcie_cfg_unrealize;
607     device_class_set_legacy_reset(dc, aspeed_pcie_cfg_reset);
608     device_class_set_props(dc, aspeed_pcie_cfg_props);
609 
610     apc->reg_ops = &aspeed_pcie_cfg_ops;
611     apc->reg_map = &aspeed_regmap;
612     apc->nr_regs = 0x100 >> 2;
613     apc->rc_msi_addr = 0x1e77005C;
614     apc->rc_bus_nr = 0x80;
615 }
616 
617 static const TypeInfo aspeed_pcie_cfg_info = {
618     .name       = TYPE_ASPEED_PCIE_CFG,
619     .parent     = TYPE_SYS_BUS_DEVICE,
620     .instance_init = aspeed_pcie_cfg_instance_init,
621     .instance_size = sizeof(AspeedPCIECfgState),
622     .class_init = aspeed_pcie_cfg_class_init,
623     .class_size = sizeof(AspeedPCIECfgClass),
624 };
625 
626 /*
627  * PCIe PHY
628  *
629  * PCIe Host Controller (PCIEH)
630  */
631 
632 /* AST2600 */
633 REG32(PEHR_ID,     0x00)
634     FIELD(PEHR_ID, DEV, 16, 16)
635 REG32(PEHR_CLASS_CODE,  0x04)
636 REG32(PEHR_DATALINK,    0x10)
637 REG32(PEHR_PROTECT,     0x7C)
638     FIELD(PEHR_PROTECT, LOCK, 0, 8)
639 REG32(PEHR_LINK,        0xC0)
640     FIELD(PEHR_LINK, STS, 5, 1)
641 
642 #define ASPEED_PCIE_PHY_UNLOCK  0xA8
643 
644 static uint64_t aspeed_pcie_phy_read(void *opaque, hwaddr addr,
645                                      unsigned int size)
646 {
647     AspeedPCIEPhyState *s = ASPEED_PCIE_PHY(opaque);
648     uint32_t reg = addr >> 2;
649     uint32_t value = 0;
650 
651     value = s->regs[reg];
652 
653     trace_aspeed_pcie_phy_read(s->id, addr, value);
654 
655     return value;
656 }
657 
658 static void aspeed_pcie_phy_write(void *opaque, hwaddr addr, uint64_t data,
659                                   unsigned int size)
660 {
661     AspeedPCIEPhyState *s = ASPEED_PCIE_PHY(opaque);
662     uint32_t reg = addr >> 2;
663 
664     trace_aspeed_pcie_phy_write(s->id, addr, data);
665 
666     switch (reg) {
667     case R_PEHR_PROTECT:
668         data &= R_PEHR_PROTECT_LOCK_MASK;
669         s->regs[reg] = !!(data == ASPEED_PCIE_PHY_UNLOCK);
670         break;
671     default:
672         s->regs[reg] = data;
673         break;
674     }
675 }
676 
677 static const MemoryRegionOps aspeed_pcie_phy_ops = {
678     .read = aspeed_pcie_phy_read,
679     .write = aspeed_pcie_phy_write,
680     .endianness = DEVICE_LITTLE_ENDIAN,
681     .valid = {
682         .min_access_size = 1,
683         .max_access_size = 4,
684     },
685 };
686 
687 static void aspeed_pcie_phy_reset(DeviceState *dev)
688 {
689     AspeedPCIEPhyState *s = ASPEED_PCIE_PHY(dev);
690     AspeedPCIEPhyClass *apc = ASPEED_PCIE_PHY_GET_CLASS(s);
691 
692     memset(s->regs, 0, apc->nr_regs << 2);
693 
694     s->regs[R_PEHR_ID] =
695         (0x1150 << R_PEHR_ID_DEV_SHIFT) | PCI_VENDOR_ID_ASPEED;
696     s->regs[R_PEHR_CLASS_CODE] = 0x06040006;
697     s->regs[R_PEHR_DATALINK] = 0xD7040022;
698     s->regs[R_PEHR_LINK] = R_PEHR_LINK_STS_MASK;
699 }
700 
701 static void aspeed_pcie_phy_realize(DeviceState *dev, Error **errp)
702 {
703     AspeedPCIEPhyState *s = ASPEED_PCIE_PHY(dev);
704     AspeedPCIEPhyClass *apc = ASPEED_PCIE_PHY_GET_CLASS(s);
705     SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
706     g_autofree char *name;
707 
708     s->regs = g_new(uint32_t, apc->nr_regs);
709     name = g_strdup_printf(TYPE_ASPEED_PCIE_PHY ".regs.%d", s->id);
710     memory_region_init_io(&s->mmio, OBJECT(s), &aspeed_pcie_phy_ops, s, name,
711                           apc->nr_regs << 2);
712     sysbus_init_mmio(sbd, &s->mmio);
713 }
714 
715 static void aspeed_pcie_phy_unrealize(DeviceState *dev)
716 {
717     AspeedPCIEPhyState *s = ASPEED_PCIE_PHY(dev);
718 
719     g_free(s->regs);
720     s->regs = NULL;
721 }
722 
723 static const Property aspeed_pcie_phy_props[] = {
724     DEFINE_PROP_UINT32("id", AspeedPCIEPhyState, id, 0),
725 };
726 
727 static void aspeed_pcie_phy_class_init(ObjectClass *klass, const void *data)
728 {
729     DeviceClass *dc = DEVICE_CLASS(klass);
730     AspeedPCIEPhyClass *apc = ASPEED_PCIE_PHY_CLASS(klass);
731 
732     dc->desc = "ASPEED PCIe Phy";
733     dc->realize = aspeed_pcie_phy_realize;
734     dc->unrealize = aspeed_pcie_phy_unrealize;
735     device_class_set_legacy_reset(dc, aspeed_pcie_phy_reset);
736     device_class_set_props(dc, aspeed_pcie_phy_props);
737 
738     apc->nr_regs = 0x100 >> 2;
739 }
740 
741 static const TypeInfo aspeed_pcie_phy_info = {
742     .name       = TYPE_ASPEED_PCIE_PHY,
743     .parent     = TYPE_SYS_BUS_DEVICE,
744     .instance_size = sizeof(AspeedPCIEPhyState),
745     .class_init = aspeed_pcie_phy_class_init,
746     .class_size = sizeof(AspeedPCIEPhyClass),
747 };
748 
749 static void aspeed_pcie_register_types(void)
750 {
751     type_register_static(&aspeed_pcie_root_info);
752     type_register_static(&aspeed_pcie_rc_info);
753     type_register_static(&aspeed_pcie_cfg_info);
754     type_register_static(&aspeed_pcie_phy_info);
755 }
756 
757 type_init(aspeed_pcie_register_types);
758 
759