xref: /openbmc/qemu/hw/pci-host/astro.c (revision e029bb00)
1*e029bb00SHelge Deller /*
2*e029bb00SHelge Deller  * HP-PARISC Astro/Pluto/Ike/REO system bus adapter (SBA)
3*e029bb00SHelge Deller  * with Elroy PCI bus (LBA) adapter emulation
4*e029bb00SHelge Deller  * Found in C3000 and similar machines
5*e029bb00SHelge Deller  *
6*e029bb00SHelge Deller  * (C) 2023 by Helge Deller <deller@gmx.de>
7*e029bb00SHelge Deller  *
8*e029bb00SHelge Deller  * This work is licensed under the GNU GPL license version 2 or later.
9*e029bb00SHelge Deller  *
10*e029bb00SHelge Deller  * Chip documentation is available at:
11*e029bb00SHelge Deller  * https://parisc.wiki.kernel.org/index.php/Technical_Documentation
12*e029bb00SHelge Deller  *
13*e029bb00SHelge Deller  * TODO:
14*e029bb00SHelge Deller  * - All user-added devices are currently attached to the first
15*e029bb00SHelge Deller  *   Elroy (PCI bus) only for now. To fix this additional work in
16*e029bb00SHelge Deller  *   SeaBIOS and this driver is needed. See "user_creatable" flag below.
17*e029bb00SHelge Deller  * - GMMIO (Greater than 4 GB MMIO) register
18*e029bb00SHelge Deller  */
19*e029bb00SHelge Deller 
20*e029bb00SHelge Deller #define TYPE_ASTRO_IOMMU_MEMORY_REGION "astro-iommu-memory-region"
21*e029bb00SHelge Deller 
22*e029bb00SHelge Deller #include "qemu/osdep.h"
23*e029bb00SHelge Deller #include "qemu/module.h"
24*e029bb00SHelge Deller #include "qemu/units.h"
25*e029bb00SHelge Deller #include "qapi/error.h"
26*e029bb00SHelge Deller #include "hw/irq.h"
27*e029bb00SHelge Deller #include "hw/pci/pci_device.h"
28*e029bb00SHelge Deller #include "hw/pci/pci_bus.h"
29*e029bb00SHelge Deller #include "hw/qdev-properties.h"
30*e029bb00SHelge Deller #include "hw/pci-host/astro.h"
31*e029bb00SHelge Deller #include "hw/hppa/hppa_hardware.h"
32*e029bb00SHelge Deller #include "migration/vmstate.h"
33*e029bb00SHelge Deller #include "trace.h"
34*e029bb00SHelge Deller #include "qom/object.h"
35*e029bb00SHelge Deller 
36*e029bb00SHelge Deller /*
37*e029bb00SHelge Deller  * Helper functions
38*e029bb00SHelge Deller  */
39*e029bb00SHelge Deller 
40*e029bb00SHelge Deller static uint64_t mask_32bit_val(hwaddr addr, unsigned size, uint64_t val)
41*e029bb00SHelge Deller {
42*e029bb00SHelge Deller     if (size == 8) {
43*e029bb00SHelge Deller         return val;
44*e029bb00SHelge Deller     }
45*e029bb00SHelge Deller     if (addr & 4) {
46*e029bb00SHelge Deller         val >>= 32;
47*e029bb00SHelge Deller     } else {
48*e029bb00SHelge Deller         val = (uint32_t) val;
49*e029bb00SHelge Deller     }
50*e029bb00SHelge Deller     return val;
51*e029bb00SHelge Deller }
52*e029bb00SHelge Deller 
53*e029bb00SHelge Deller static void put_val_in_int64(uint64_t *p, hwaddr addr, unsigned size,
54*e029bb00SHelge Deller                              uint64_t val)
55*e029bb00SHelge Deller {
56*e029bb00SHelge Deller     if (size == 8) {
57*e029bb00SHelge Deller         *p = val;
58*e029bb00SHelge Deller     } else if (size == 4) {
59*e029bb00SHelge Deller         if (addr & 4) {
60*e029bb00SHelge Deller             *p = ((*p << 32) >> 32) | (val << 32);
61*e029bb00SHelge Deller         } else {
62*e029bb00SHelge Deller             *p = ((*p >> 32) << 32) | (uint32_t) val;
63*e029bb00SHelge Deller         }
64*e029bb00SHelge Deller     }
65*e029bb00SHelge Deller }
66*e029bb00SHelge Deller 
67*e029bb00SHelge Deller static void put_val_in_arrary(uint64_t *array, hwaddr start_addr,
68*e029bb00SHelge Deller                               hwaddr addr, unsigned size, uint64_t val)
69*e029bb00SHelge Deller {
70*e029bb00SHelge Deller     int index;
71*e029bb00SHelge Deller 
72*e029bb00SHelge Deller     index = (addr - start_addr) / 8;
73*e029bb00SHelge Deller     put_val_in_int64(&array[index], addr, size, val);
74*e029bb00SHelge Deller }
75*e029bb00SHelge Deller 
76*e029bb00SHelge Deller 
77*e029bb00SHelge Deller /*
78*e029bb00SHelge Deller  * The Elroy PCI host bridge. We have at least 4 of those under Astro.
79*e029bb00SHelge Deller  */
80*e029bb00SHelge Deller 
81*e029bb00SHelge Deller static MemTxResult elroy_chip_read_with_attrs(void *opaque, hwaddr addr,
82*e029bb00SHelge Deller                                              uint64_t *data, unsigned size,
83*e029bb00SHelge Deller                                              MemTxAttrs attrs)
84*e029bb00SHelge Deller {
85*e029bb00SHelge Deller     MemTxResult ret = MEMTX_OK;
86*e029bb00SHelge Deller     ElroyState *s = opaque;
87*e029bb00SHelge Deller     uint64_t val = -1;
88*e029bb00SHelge Deller     int index;
89*e029bb00SHelge Deller 
90*e029bb00SHelge Deller     switch ((addr >> 3) << 3) {
91*e029bb00SHelge Deller     case 0x0008:
92*e029bb00SHelge Deller         val = 0x6000005; /* func_class */
93*e029bb00SHelge Deller         break;
94*e029bb00SHelge Deller     case 0x0058:
95*e029bb00SHelge Deller         /*
96*e029bb00SHelge Deller          * Scratch register, but firmware initializes it with the
97*e029bb00SHelge Deller          * PCI BUS number and Linux/HP-UX uses it then.
98*e029bb00SHelge Deller          */
99*e029bb00SHelge Deller         val = s->pci_bus_num;
100*e029bb00SHelge Deller         /* Upper byte holds the end of this bus number */
101*e029bb00SHelge Deller         val |= s->pci_bus_num << 8;
102*e029bb00SHelge Deller         break;
103*e029bb00SHelge Deller     case 0x0080:
104*e029bb00SHelge Deller         val = s->arb_mask; /* set ARB mask */
105*e029bb00SHelge Deller         break;
106*e029bb00SHelge Deller     case 0x0108:
107*e029bb00SHelge Deller         val = s->status_control;
108*e029bb00SHelge Deller         break;
109*e029bb00SHelge Deller     case 0x200 ... 0x250 - 1: /* LMMIO, GMMIO, WLMMIO, WGMMIO, ... */
110*e029bb00SHelge Deller         index = (addr - 0x200) / 8;
111*e029bb00SHelge Deller         val = s->mmio_base[index];
112*e029bb00SHelge Deller         break;
113*e029bb00SHelge Deller     case 0x0680:
114*e029bb00SHelge Deller         val = s->error_config;
115*e029bb00SHelge Deller         break;
116*e029bb00SHelge Deller     case 0x0688:
117*e029bb00SHelge Deller         val = 0;                /* ERROR_STATUS */
118*e029bb00SHelge Deller         break;
119*e029bb00SHelge Deller     case 0x0800:                /* IOSAPIC_REG_SELECT */
120*e029bb00SHelge Deller         val = s->iosapic_reg_select;
121*e029bb00SHelge Deller         break;
122*e029bb00SHelge Deller     case 0x0808:
123*e029bb00SHelge Deller         val = UINT64_MAX;            /* XXX: tbc. */
124*e029bb00SHelge Deller         g_assert_not_reached();
125*e029bb00SHelge Deller         break;
126*e029bb00SHelge Deller     case 0x0810:                /* IOSAPIC_REG_WINDOW */
127*e029bb00SHelge Deller         switch (s->iosapic_reg_select) {
128*e029bb00SHelge Deller         case 0x01:              /* IOSAPIC_REG_VERSION */
129*e029bb00SHelge Deller             val = (32 << 16) | 1; /* upper 16bit holds max entries */
130*e029bb00SHelge Deller             break;
131*e029bb00SHelge Deller         default:
132*e029bb00SHelge Deller             if (s->iosapic_reg_select < ARRAY_SIZE(s->iosapic_reg)) {
133*e029bb00SHelge Deller                 val = s->iosapic_reg[s->iosapic_reg_select];
134*e029bb00SHelge Deller             } else {
135*e029bb00SHelge Deller                 trace_iosapic_reg_read(s->iosapic_reg_select, size, val);
136*e029bb00SHelge Deller                 g_assert_not_reached();
137*e029bb00SHelge Deller             }
138*e029bb00SHelge Deller         }
139*e029bb00SHelge Deller         trace_iosapic_reg_read(s->iosapic_reg_select, size, val);
140*e029bb00SHelge Deller         break;
141*e029bb00SHelge Deller     default:
142*e029bb00SHelge Deller         trace_elroy_read(addr, size, val);
143*e029bb00SHelge Deller         g_assert_not_reached();
144*e029bb00SHelge Deller     }
145*e029bb00SHelge Deller     trace_elroy_read(addr, size, val);
146*e029bb00SHelge Deller 
147*e029bb00SHelge Deller     /* for 32-bit accesses mask return value */
148*e029bb00SHelge Deller     val = mask_32bit_val(addr, size, val);
149*e029bb00SHelge Deller 
150*e029bb00SHelge Deller     trace_astro_chip_read(addr, size, val);
151*e029bb00SHelge Deller     *data = val;
152*e029bb00SHelge Deller     return ret;
153*e029bb00SHelge Deller }
154*e029bb00SHelge Deller 
155*e029bb00SHelge Deller 
156*e029bb00SHelge Deller static MemTxResult elroy_chip_write_with_attrs(void *opaque, hwaddr addr,
157*e029bb00SHelge Deller                                               uint64_t val, unsigned size,
158*e029bb00SHelge Deller                                               MemTxAttrs attrs)
159*e029bb00SHelge Deller {
160*e029bb00SHelge Deller     ElroyState *s = opaque;
161*e029bb00SHelge Deller     int i;
162*e029bb00SHelge Deller 
163*e029bb00SHelge Deller     trace_elroy_write(addr, size, val);
164*e029bb00SHelge Deller 
165*e029bb00SHelge Deller     switch ((addr >> 3) << 3) {
166*e029bb00SHelge Deller     case 0x080:
167*e029bb00SHelge Deller         put_val_in_int64(&s->arb_mask, addr, size, val);
168*e029bb00SHelge Deller         break;
169*e029bb00SHelge Deller     case 0x0108:
170*e029bb00SHelge Deller         put_val_in_int64(&s->status_control, addr, size, val);
171*e029bb00SHelge Deller         break;
172*e029bb00SHelge Deller     case 0x200 ... 0x250 - 1:   /* LMMIO, GMMIO, WLMMIO, WGMMIO, ... */
173*e029bb00SHelge Deller         put_val_in_arrary(s->mmio_base, 0x200, addr, size, val);
174*e029bb00SHelge Deller         break;
175*e029bb00SHelge Deller     case 0x0680:
176*e029bb00SHelge Deller         put_val_in_int64(&s->error_config, addr, size, val);
177*e029bb00SHelge Deller         break;
178*e029bb00SHelge Deller     case 0x0800:                /* IOSAPIC_REG_SELECT */
179*e029bb00SHelge Deller         s->iosapic_reg_select = val;
180*e029bb00SHelge Deller         break;
181*e029bb00SHelge Deller     case 0x0810:                /* IOSAPIC_REG_WINDOW */
182*e029bb00SHelge Deller         trace_iosapic_reg_write(s->iosapic_reg_select, size, val);
183*e029bb00SHelge Deller         if (s->iosapic_reg_select < ARRAY_SIZE(s->iosapic_reg)) {
184*e029bb00SHelge Deller             s->iosapic_reg[s->iosapic_reg_select] = val;
185*e029bb00SHelge Deller         } else {
186*e029bb00SHelge Deller             g_assert_not_reached();
187*e029bb00SHelge Deller         }
188*e029bb00SHelge Deller         break;
189*e029bb00SHelge Deller     case 0x0840:                /* IOSAPIC_REG_EOI */
190*e029bb00SHelge Deller         val = le64_to_cpu(val);
191*e029bb00SHelge Deller         val &= 63;
192*e029bb00SHelge Deller         for (i = 0; i < ELROY_IRQS; i++) {
193*e029bb00SHelge Deller             if ((s->iosapic_reg[0x10 + 2 * i] & 63) == val) {
194*e029bb00SHelge Deller                 s->ilr &= ~(1ull << i);
195*e029bb00SHelge Deller             }
196*e029bb00SHelge Deller         }
197*e029bb00SHelge Deller         break;
198*e029bb00SHelge Deller     default:
199*e029bb00SHelge Deller         g_assert_not_reached();
200*e029bb00SHelge Deller     }
201*e029bb00SHelge Deller     return MEMTX_OK;
202*e029bb00SHelge Deller }
203*e029bb00SHelge Deller 
204*e029bb00SHelge Deller static const MemoryRegionOps elroy_chip_ops = {
205*e029bb00SHelge Deller     .read_with_attrs = elroy_chip_read_with_attrs,
206*e029bb00SHelge Deller     .write_with_attrs = elroy_chip_write_with_attrs,
207*e029bb00SHelge Deller     .endianness = DEVICE_LITTLE_ENDIAN,
208*e029bb00SHelge Deller     .valid = {
209*e029bb00SHelge Deller         .min_access_size = 4,
210*e029bb00SHelge Deller         .max_access_size = 8,
211*e029bb00SHelge Deller     },
212*e029bb00SHelge Deller     .impl = {
213*e029bb00SHelge Deller         .min_access_size = 4,
214*e029bb00SHelge Deller         .max_access_size = 8,
215*e029bb00SHelge Deller     },
216*e029bb00SHelge Deller };
217*e029bb00SHelge Deller 
218*e029bb00SHelge Deller 
219*e029bb00SHelge Deller /* Unlike pci_config_data_le_ops, no check of high bit set in config_reg.  */
220*e029bb00SHelge Deller 
221*e029bb00SHelge Deller static uint64_t elroy_config_data_read(void *opaque, hwaddr addr, unsigned len)
222*e029bb00SHelge Deller {
223*e029bb00SHelge Deller     uint64_t val;
224*e029bb00SHelge Deller 
225*e029bb00SHelge Deller     PCIHostState *s = opaque;
226*e029bb00SHelge Deller     val = pci_data_read(s->bus, s->config_reg | (addr & 3), len);
227*e029bb00SHelge Deller     trace_elroy_pci_config_data_read(s->config_reg | (addr & 3), len, val);
228*e029bb00SHelge Deller     return val;
229*e029bb00SHelge Deller }
230*e029bb00SHelge Deller 
231*e029bb00SHelge Deller static void elroy_config_data_write(void *opaque, hwaddr addr,
232*e029bb00SHelge Deller                                    uint64_t val, unsigned len)
233*e029bb00SHelge Deller {
234*e029bb00SHelge Deller     PCIHostState *s = opaque;
235*e029bb00SHelge Deller     pci_data_write(s->bus, s->config_reg | (addr & 3), val, len);
236*e029bb00SHelge Deller     trace_elroy_pci_config_data_write(s->config_reg | (addr & 3), len, val);
237*e029bb00SHelge Deller }
238*e029bb00SHelge Deller 
239*e029bb00SHelge Deller static const MemoryRegionOps elroy_config_data_ops = {
240*e029bb00SHelge Deller     .read = elroy_config_data_read,
241*e029bb00SHelge Deller     .write = elroy_config_data_write,
242*e029bb00SHelge Deller     .endianness = DEVICE_LITTLE_ENDIAN,
243*e029bb00SHelge Deller };
244*e029bb00SHelge Deller 
245*e029bb00SHelge Deller static uint64_t elroy_config_addr_read(void *opaque, hwaddr addr, unsigned len)
246*e029bb00SHelge Deller {
247*e029bb00SHelge Deller     ElroyState *s = opaque;
248*e029bb00SHelge Deller     return s->config_reg_elroy;
249*e029bb00SHelge Deller }
250*e029bb00SHelge Deller 
251*e029bb00SHelge Deller static void elroy_config_addr_write(void *opaque, hwaddr addr,
252*e029bb00SHelge Deller                                    uint64_t val, unsigned len)
253*e029bb00SHelge Deller {
254*e029bb00SHelge Deller     PCIHostState *s = opaque;
255*e029bb00SHelge Deller     ElroyState *es = opaque;
256*e029bb00SHelge Deller     es->config_reg_elroy = val; /* keep a copy of original value */
257*e029bb00SHelge Deller     s->config_reg = val;
258*e029bb00SHelge Deller }
259*e029bb00SHelge Deller 
260*e029bb00SHelge Deller static const MemoryRegionOps elroy_config_addr_ops = {
261*e029bb00SHelge Deller     .read = elroy_config_addr_read,
262*e029bb00SHelge Deller     .write = elroy_config_addr_write,
263*e029bb00SHelge Deller     .valid.min_access_size = 4,
264*e029bb00SHelge Deller     .valid.max_access_size = 8,
265*e029bb00SHelge Deller     .endianness = DEVICE_LITTLE_ENDIAN,
266*e029bb00SHelge Deller };
267*e029bb00SHelge Deller 
268*e029bb00SHelge Deller 
269*e029bb00SHelge Deller /*
270*e029bb00SHelge Deller  * A subroutine of astro_translate_iommu that builds an IOMMUTLBEntry using the
271*e029bb00SHelge Deller  * given translated address and mask.
272*e029bb00SHelge Deller  */
273*e029bb00SHelge Deller static bool make_iommu_tlbe(hwaddr addr, hwaddr taddr, hwaddr mask,
274*e029bb00SHelge Deller                             IOMMUTLBEntry *ret)
275*e029bb00SHelge Deller {
276*e029bb00SHelge Deller     hwaddr tce_mask = ~((1ull << 12) - 1);
277*e029bb00SHelge Deller     ret->target_as = &address_space_memory;
278*e029bb00SHelge Deller     ret->iova = addr & tce_mask;
279*e029bb00SHelge Deller     ret->translated_addr = taddr & tce_mask;
280*e029bb00SHelge Deller     ret->addr_mask = ~tce_mask;
281*e029bb00SHelge Deller     ret->perm = IOMMU_RW;
282*e029bb00SHelge Deller     return true;
283*e029bb00SHelge Deller }
284*e029bb00SHelge Deller 
285*e029bb00SHelge Deller /* Handle PCI-to-system address translation.  */
286*e029bb00SHelge Deller static IOMMUTLBEntry astro_translate_iommu(IOMMUMemoryRegion *iommu,
287*e029bb00SHelge Deller                                              hwaddr addr,
288*e029bb00SHelge Deller                                              IOMMUAccessFlags flag,
289*e029bb00SHelge Deller                                              int iommu_idx)
290*e029bb00SHelge Deller {
291*e029bb00SHelge Deller     AstroState *s = container_of(iommu, AstroState, iommu);
292*e029bb00SHelge Deller     IOMMUTLBEntry ret = {
293*e029bb00SHelge Deller         .target_as = &address_space_memory,
294*e029bb00SHelge Deller         .iova = addr,
295*e029bb00SHelge Deller         .translated_addr = 0,
296*e029bb00SHelge Deller         .addr_mask = ~(hwaddr)0,
297*e029bb00SHelge Deller         .perm = IOMMU_NONE,
298*e029bb00SHelge Deller     };
299*e029bb00SHelge Deller     hwaddr pdir_ptr, index, a, ibase;
300*e029bb00SHelge Deller     hwaddr addr_mask = 0xfff; /* 4k translation */
301*e029bb00SHelge Deller     uint64_t entry;
302*e029bb00SHelge Deller 
303*e029bb00SHelge Deller #define IOVP_SHIFT              12   /* equals PAGE_SHIFT */
304*e029bb00SHelge Deller #define PDIR_INDEX(iovp)        ((iovp) >> IOVP_SHIFT)
305*e029bb00SHelge Deller #define IOVP_MASK               PAGE_MASK
306*e029bb00SHelge Deller #define SBA_PDIR_VALID_BIT      0x8000000000000000ULL
307*e029bb00SHelge Deller 
308*e029bb00SHelge Deller     /* "range enable" flag cleared? */
309*e029bb00SHelge Deller     if ((s->tlb_ibase & 1) == 0) {
310*e029bb00SHelge Deller         make_iommu_tlbe(addr, addr, addr_mask, &ret);
311*e029bb00SHelge Deller         return ret;
312*e029bb00SHelge Deller     }
313*e029bb00SHelge Deller 
314*e029bb00SHelge Deller     a = addr;
315*e029bb00SHelge Deller     ibase = s->tlb_ibase & ~1ULL;
316*e029bb00SHelge Deller     if ((a & s->tlb_imask) != ibase) {
317*e029bb00SHelge Deller         /* do not translate this one! */
318*e029bb00SHelge Deller         make_iommu_tlbe(addr, addr, addr_mask, &ret);
319*e029bb00SHelge Deller         return ret;
320*e029bb00SHelge Deller     }
321*e029bb00SHelge Deller     index = PDIR_INDEX(a);
322*e029bb00SHelge Deller     pdir_ptr = s->tlb_pdir_base + index * sizeof(entry);
323*e029bb00SHelge Deller     entry = ldq_le_phys(&address_space_memory, pdir_ptr);
324*e029bb00SHelge Deller     if (!(entry & SBA_PDIR_VALID_BIT)) { /* I/O PDIR entry valid ? */
325*e029bb00SHelge Deller         g_assert_not_reached();
326*e029bb00SHelge Deller         goto failure;
327*e029bb00SHelge Deller     }
328*e029bb00SHelge Deller     entry &= ~SBA_PDIR_VALID_BIT;
329*e029bb00SHelge Deller     entry >>= IOVP_SHIFT;
330*e029bb00SHelge Deller     entry <<= 12;
331*e029bb00SHelge Deller     entry |= addr & 0xfff;
332*e029bb00SHelge Deller     make_iommu_tlbe(addr, entry, addr_mask, &ret);
333*e029bb00SHelge Deller     goto success;
334*e029bb00SHelge Deller 
335*e029bb00SHelge Deller  failure:
336*e029bb00SHelge Deller     ret = (IOMMUTLBEntry) { .perm = IOMMU_NONE };
337*e029bb00SHelge Deller  success:
338*e029bb00SHelge Deller     return ret;
339*e029bb00SHelge Deller }
340*e029bb00SHelge Deller 
341*e029bb00SHelge Deller static AddressSpace *elroy_pcihost_set_iommu(PCIBus *bus, void *opaque,
342*e029bb00SHelge Deller                                             int devfn)
343*e029bb00SHelge Deller {
344*e029bb00SHelge Deller     ElroyState *s = opaque;
345*e029bb00SHelge Deller     return &s->astro->iommu_as;
346*e029bb00SHelge Deller }
347*e029bb00SHelge Deller 
348*e029bb00SHelge Deller /*
349*e029bb00SHelge Deller  * Encoding in IOSAPIC:
350*e029bb00SHelge Deller  * base_addr == 0xfffa0000, we want to get 0xa0ff0000.
351*e029bb00SHelge Deller  * eid  0x0ff00000 -> 0x00ff0000
352*e029bb00SHelge Deller  * id   0x000ff000 -> 0xff000000
353*e029bb00SHelge Deller  */
354*e029bb00SHelge Deller #define SWIZZLE_HPA(a) \
355*e029bb00SHelge Deller         ((((a) & 0x0ff00000) >> 4) | (((a) & 0x000ff000) << 12))
356*e029bb00SHelge Deller #define UNSWIZZLE_HPA(a) \
357*e029bb00SHelge Deller         (((((a) << 4) & 0x0ff00000) | (((a) >> 12) & 0x000ff000) | 0xf0000000))
358*e029bb00SHelge Deller 
359*e029bb00SHelge Deller /* bits in the "low" I/O Sapic IRdT entry */
360*e029bb00SHelge Deller #define IOSAPIC_IRDT_DISABLE      0x10000 /* if bit is set, mask this irq */
361*e029bb00SHelge Deller #define IOSAPIC_IRDT_PO_LOW       0x02000
362*e029bb00SHelge Deller #define IOSAPIC_IRDT_LEVEL_TRIG   0x08000
363*e029bb00SHelge Deller #define IOSAPIC_IRDT_MODE_LPRI    0x00100
364*e029bb00SHelge Deller 
365*e029bb00SHelge Deller #define CPU_IRQ_OFFSET            2
366*e029bb00SHelge Deller 
367*e029bb00SHelge Deller static void elroy_set_irq(void *opaque, int irq, int level)
368*e029bb00SHelge Deller {
369*e029bb00SHelge Deller     ElroyState *s = opaque;
370*e029bb00SHelge Deller     uint32_t bit;
371*e029bb00SHelge Deller     uint32_t old_ilr = s->ilr;
372*e029bb00SHelge Deller     hwaddr cpu_hpa;
373*e029bb00SHelge Deller     uint32_t val;
374*e029bb00SHelge Deller 
375*e029bb00SHelge Deller     val     = s->iosapic_reg[0x10 + 2 * irq];
376*e029bb00SHelge Deller     cpu_hpa = s->iosapic_reg[0x11 + 2 * irq];
377*e029bb00SHelge Deller     /* low nibble of val has value to write into CPU irq reg */
378*e029bb00SHelge Deller     bit     = 1u << (val & (ELROY_IRQS - 1));
379*e029bb00SHelge Deller     cpu_hpa = UNSWIZZLE_HPA(cpu_hpa);
380*e029bb00SHelge Deller 
381*e029bb00SHelge Deller     if (level && (!(val & IOSAPIC_IRDT_DISABLE)) && cpu_hpa) {
382*e029bb00SHelge Deller         uint32_t ena = bit & ~old_ilr;
383*e029bb00SHelge Deller         s->ilr = old_ilr | bit;
384*e029bb00SHelge Deller         if (ena != 0) {
385*e029bb00SHelge Deller             stl_be_phys(&address_space_memory, cpu_hpa, val & 63);
386*e029bb00SHelge Deller         }
387*e029bb00SHelge Deller     } else {
388*e029bb00SHelge Deller         s->ilr = old_ilr & ~bit;
389*e029bb00SHelge Deller     }
390*e029bb00SHelge Deller }
391*e029bb00SHelge Deller 
392*e029bb00SHelge Deller static int elroy_pci_map_irq(PCIDevice *d, int irq_num)
393*e029bb00SHelge Deller {
394*e029bb00SHelge Deller     int slot = PCI_SLOT(d->devfn);
395*e029bb00SHelge Deller 
396*e029bb00SHelge Deller     assert(irq_num >= 0 && irq_num < ELROY_IRQS);
397*e029bb00SHelge Deller     return slot & (ELROY_IRQS - 1);
398*e029bb00SHelge Deller }
399*e029bb00SHelge Deller 
400*e029bb00SHelge Deller static void elroy_reset(DeviceState *dev)
401*e029bb00SHelge Deller {
402*e029bb00SHelge Deller     ElroyState *s = ELROY_PCI_HOST_BRIDGE(dev);
403*e029bb00SHelge Deller     int irq;
404*e029bb00SHelge Deller 
405*e029bb00SHelge Deller     /*
406*e029bb00SHelge Deller      * Make sure to disable interrupts at reboot, otherwise the Linux kernel
407*e029bb00SHelge Deller      * serial8250_config_port() in drivers/tty/serial/8250/8250_port.c
408*e029bb00SHelge Deller      * will hang during autoconfig().
409*e029bb00SHelge Deller      */
410*e029bb00SHelge Deller     s->ilr = 0;
411*e029bb00SHelge Deller     for (irq = 0; irq < ELROY_IRQS; irq++) {
412*e029bb00SHelge Deller         s->iosapic_reg[0x10 + 2 * irq] = IOSAPIC_IRDT_PO_LOW |
413*e029bb00SHelge Deller                 IOSAPIC_IRDT_LEVEL_TRIG | (irq + CPU_IRQ_OFFSET) |
414*e029bb00SHelge Deller                 IOSAPIC_IRDT_DISABLE;
415*e029bb00SHelge Deller         s->iosapic_reg[0x11 + 2 * irq] = SWIZZLE_HPA(CPU_HPA);
416*e029bb00SHelge Deller     }
417*e029bb00SHelge Deller }
418*e029bb00SHelge Deller 
419*e029bb00SHelge Deller static void elroy_pcihost_init(Object *obj)
420*e029bb00SHelge Deller {
421*e029bb00SHelge Deller     ElroyState *s = ELROY_PCI_HOST_BRIDGE(obj);
422*e029bb00SHelge Deller     PCIHostState *phb = PCI_HOST_BRIDGE(obj);
423*e029bb00SHelge Deller     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
424*e029bb00SHelge Deller 
425*e029bb00SHelge Deller     /* Elroy config access from CPU.  */
426*e029bb00SHelge Deller     memory_region_init_io(&s->this_mem, OBJECT(s), &elroy_chip_ops,
427*e029bb00SHelge Deller                           s, "elroy", 0x2000);
428*e029bb00SHelge Deller 
429*e029bb00SHelge Deller     /* Elroy PCI config. */
430*e029bb00SHelge Deller     memory_region_init_io(&phb->conf_mem, OBJECT(phb),
431*e029bb00SHelge Deller                           &elroy_config_addr_ops, DEVICE(s),
432*e029bb00SHelge Deller                           "pci-conf-idx", 8);
433*e029bb00SHelge Deller     memory_region_init_io(&phb->data_mem, OBJECT(phb),
434*e029bb00SHelge Deller                           &elroy_config_data_ops, DEVICE(s),
435*e029bb00SHelge Deller                           "pci-conf-data", 8);
436*e029bb00SHelge Deller     memory_region_add_subregion(&s->this_mem, 0x40,
437*e029bb00SHelge Deller                                 &phb->conf_mem);
438*e029bb00SHelge Deller     memory_region_add_subregion(&s->this_mem, 0x48,
439*e029bb00SHelge Deller                                 &phb->data_mem);
440*e029bb00SHelge Deller 
441*e029bb00SHelge Deller     /* Elroy PCI bus memory.  */
442*e029bb00SHelge Deller     memory_region_init(&s->pci_mmio, OBJECT(s), "pci-mmio", UINT64_MAX);
443*e029bb00SHelge Deller     memory_region_init_io(&s->pci_io, OBJECT(s), &unassigned_io_ops, obj,
444*e029bb00SHelge Deller                             "pci-isa-mmio",
445*e029bb00SHelge Deller                             ((uint32_t) IOS_DIST_BASE_SIZE) / ROPES_PER_IOC);
446*e029bb00SHelge Deller 
447*e029bb00SHelge Deller     phb->bus = pci_register_root_bus(DEVICE(s), "pci",
448*e029bb00SHelge Deller                                      elroy_set_irq, elroy_pci_map_irq, s,
449*e029bb00SHelge Deller                                      &s->pci_mmio, &s->pci_io,
450*e029bb00SHelge Deller                                      PCI_DEVFN(0, 0), ELROY_IRQS, TYPE_PCI_BUS);
451*e029bb00SHelge Deller 
452*e029bb00SHelge Deller     sysbus_init_mmio(sbd, &s->this_mem);
453*e029bb00SHelge Deller 
454*e029bb00SHelge Deller     qdev_init_gpio_in(DEVICE(obj), elroy_set_irq, ELROY_IRQS);
455*e029bb00SHelge Deller }
456*e029bb00SHelge Deller 
457*e029bb00SHelge Deller static Property elroy_pcihost_properties[] = {
458*e029bb00SHelge Deller     DEFINE_PROP_END_OF_LIST(),
459*e029bb00SHelge Deller };
460*e029bb00SHelge Deller 
461*e029bb00SHelge Deller static const VMStateDescription vmstate_elroy = {
462*e029bb00SHelge Deller     .name = "Elroy",
463*e029bb00SHelge Deller     .version_id = 1,
464*e029bb00SHelge Deller     .minimum_version_id = 1,
465*e029bb00SHelge Deller     .fields = (VMStateField[]) {
466*e029bb00SHelge Deller         VMSTATE_UINT64(hpa, ElroyState),
467*e029bb00SHelge Deller         VMSTATE_UINT32(pci_bus_num, ElroyState),
468*e029bb00SHelge Deller         VMSTATE_UINT64(config_address, ElroyState),
469*e029bb00SHelge Deller         VMSTATE_UINT64(config_reg_elroy, ElroyState),
470*e029bb00SHelge Deller         VMSTATE_UINT64(status_control, ElroyState),
471*e029bb00SHelge Deller         VMSTATE_UINT64(arb_mask, ElroyState),
472*e029bb00SHelge Deller         VMSTATE_UINT64_ARRAY(mmio_base, ElroyState, (0x0250 - 0x200) / 8),
473*e029bb00SHelge Deller         VMSTATE_UINT64(error_config, ElroyState),
474*e029bb00SHelge Deller         VMSTATE_UINT32(iosapic_reg_select, ElroyState),
475*e029bb00SHelge Deller         VMSTATE_UINT64_ARRAY(iosapic_reg, ElroyState, 0x20),
476*e029bb00SHelge Deller         VMSTATE_UINT32(ilr, ElroyState),
477*e029bb00SHelge Deller         VMSTATE_END_OF_LIST()
478*e029bb00SHelge Deller     }
479*e029bb00SHelge Deller };
480*e029bb00SHelge Deller 
481*e029bb00SHelge Deller static void elroy_pcihost_class_init(ObjectClass *klass, void *data)
482*e029bb00SHelge Deller {
483*e029bb00SHelge Deller     DeviceClass *dc = DEVICE_CLASS(klass);
484*e029bb00SHelge Deller 
485*e029bb00SHelge Deller     dc->reset = elroy_reset;
486*e029bb00SHelge Deller     device_class_set_props(dc, elroy_pcihost_properties);
487*e029bb00SHelge Deller     dc->vmsd = &vmstate_elroy;
488*e029bb00SHelge Deller     dc->user_creatable = false;
489*e029bb00SHelge Deller }
490*e029bb00SHelge Deller 
491*e029bb00SHelge Deller static const TypeInfo elroy_pcihost_info = {
492*e029bb00SHelge Deller     .name          = TYPE_ELROY_PCI_HOST_BRIDGE,
493*e029bb00SHelge Deller     .parent        = TYPE_PCI_HOST_BRIDGE,
494*e029bb00SHelge Deller     .instance_init = elroy_pcihost_init,
495*e029bb00SHelge Deller     .instance_size = sizeof(ElroyState),
496*e029bb00SHelge Deller     .class_init    = elroy_pcihost_class_init,
497*e029bb00SHelge Deller };
498*e029bb00SHelge Deller 
499*e029bb00SHelge Deller static void elroy_register_types(void)
500*e029bb00SHelge Deller {
501*e029bb00SHelge Deller     type_register_static(&elroy_pcihost_info);
502*e029bb00SHelge Deller }
503*e029bb00SHelge Deller 
504*e029bb00SHelge Deller type_init(elroy_register_types)
505*e029bb00SHelge Deller 
506*e029bb00SHelge Deller 
507*e029bb00SHelge Deller static ElroyState *elroy_init(int num)
508*e029bb00SHelge Deller {
509*e029bb00SHelge Deller     DeviceState *dev;
510*e029bb00SHelge Deller 
511*e029bb00SHelge Deller     dev = qdev_new(TYPE_ELROY_PCI_HOST_BRIDGE);
512*e029bb00SHelge Deller     dev->id = g_strdup_printf("elroy%d", num);
513*e029bb00SHelge Deller     sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
514*e029bb00SHelge Deller 
515*e029bb00SHelge Deller     return ELROY_PCI_HOST_BRIDGE(dev);
516*e029bb00SHelge Deller }
517*e029bb00SHelge Deller 
518*e029bb00SHelge Deller /*
519*e029bb00SHelge Deller  * Astro Runway chip.
520*e029bb00SHelge Deller  */
521*e029bb00SHelge Deller 
522*e029bb00SHelge Deller static MemTxResult astro_chip_read_with_attrs(void *opaque, hwaddr addr,
523*e029bb00SHelge Deller                                              uint64_t *data, unsigned size,
524*e029bb00SHelge Deller                                              MemTxAttrs attrs)
525*e029bb00SHelge Deller {
526*e029bb00SHelge Deller     AstroState *s = opaque;
527*e029bb00SHelge Deller     MemTxResult ret = MEMTX_OK;
528*e029bb00SHelge Deller     uint64_t val = -1;
529*e029bb00SHelge Deller     int index;
530*e029bb00SHelge Deller 
531*e029bb00SHelge Deller     switch ((addr >> 3) << 3) {
532*e029bb00SHelge Deller     /* R2I registers */
533*e029bb00SHelge Deller     case 0x0000:        /* ID */
534*e029bb00SHelge Deller         val = (0x01 << 3) | 0x01ULL;
535*e029bb00SHelge Deller         break;
536*e029bb00SHelge Deller     case 0x0008:        /* IOC_CTRL */
537*e029bb00SHelge Deller         val = s->ioc_ctrl;
538*e029bb00SHelge Deller         break;
539*e029bb00SHelge Deller     case 0x0010:        /* TOC_CLIENT_ID */
540*e029bb00SHelge Deller         break;
541*e029bb00SHelge Deller     case 0x0030:        /* HP-UX 10.20 and 11.11 reads it. No idea. */
542*e029bb00SHelge Deller         val = -1;
543*e029bb00SHelge Deller         break;
544*e029bb00SHelge Deller     case 0x0300 ... 0x03d8:     /* LMMIO_DIRECT0_BASE... */
545*e029bb00SHelge Deller         index = (addr - 0x300) / 8;
546*e029bb00SHelge Deller         val = s->ioc_ranges[index];
547*e029bb00SHelge Deller         break;
548*e029bb00SHelge Deller     case 0x10200:
549*e029bb00SHelge Deller         val = 0;
550*e029bb00SHelge Deller         break;
551*e029bb00SHelge Deller     case 0x10220:
552*e029bb00SHelge Deller     case 0x10230:        /* HP-UX 11.11 reads it. No idea. */
553*e029bb00SHelge Deller         val = -1;
554*e029bb00SHelge Deller         break;
555*e029bb00SHelge Deller     case 0x22108:        /* IOC STATUS_CONTROL */
556*e029bb00SHelge Deller         val = s->ioc_status_ctrl;
557*e029bb00SHelge Deller         break;
558*e029bb00SHelge Deller     case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */
559*e029bb00SHelge Deller         index = (addr - 0x20200) / 8;
560*e029bb00SHelge Deller         val = s->ioc_rope_control[index];
561*e029bb00SHelge Deller         break;
562*e029bb00SHelge Deller     case 0x20040:        /* IOC Rope config */
563*e029bb00SHelge Deller         val = s->ioc_rope_config;
564*e029bb00SHelge Deller         break;
565*e029bb00SHelge Deller     case 0x20050:        /* IOC Rope debug */
566*e029bb00SHelge Deller         val = 0;
567*e029bb00SHelge Deller         break;
568*e029bb00SHelge Deller     case 0x20108:        /* IOC STATUS_CONTROL */
569*e029bb00SHelge Deller         val = s->ioc_status_control;
570*e029bb00SHelge Deller         break;
571*e029bb00SHelge Deller     case 0x20310:        /* IOC_PCOM */
572*e029bb00SHelge Deller         val = s->tlb_pcom;
573*e029bb00SHelge Deller         /* TODO: flush iommu */
574*e029bb00SHelge Deller         break;
575*e029bb00SHelge Deller     case 0x20400:
576*e029bb00SHelge Deller         val = s->ioc_flush_control;
577*e029bb00SHelge Deller         break;
578*e029bb00SHelge Deller     /* empty placeholders for non-existent elroys */
579*e029bb00SHelge Deller #define EMPTY_PORT(x) case x:    case x+8:   val = 0;          break; \
580*e029bb00SHelge Deller                       case x+40: case x+48:  val = UINT64_MAX; break;
581*e029bb00SHelge Deller         EMPTY_PORT(0x30000)
582*e029bb00SHelge Deller         EMPTY_PORT(0x32000)
583*e029bb00SHelge Deller         EMPTY_PORT(0x34000)
584*e029bb00SHelge Deller         EMPTY_PORT(0x36000)
585*e029bb00SHelge Deller         EMPTY_PORT(0x38000)
586*e029bb00SHelge Deller         EMPTY_PORT(0x3a000)
587*e029bb00SHelge Deller         EMPTY_PORT(0x3c000)
588*e029bb00SHelge Deller         EMPTY_PORT(0x3e000)
589*e029bb00SHelge Deller #undef EMPTY_PORT
590*e029bb00SHelge Deller 
591*e029bb00SHelge Deller     default:
592*e029bb00SHelge Deller         trace_astro_chip_read(addr, size, val);
593*e029bb00SHelge Deller         g_assert_not_reached();
594*e029bb00SHelge Deller     }
595*e029bb00SHelge Deller 
596*e029bb00SHelge Deller     /* for 32-bit accesses mask return value */
597*e029bb00SHelge Deller     val = mask_32bit_val(addr, size, val);
598*e029bb00SHelge Deller 
599*e029bb00SHelge Deller     trace_astro_chip_read(addr, size, val);
600*e029bb00SHelge Deller     *data = val;
601*e029bb00SHelge Deller     return ret;
602*e029bb00SHelge Deller }
603*e029bb00SHelge Deller 
604*e029bb00SHelge Deller static MemTxResult astro_chip_write_with_attrs(void *opaque, hwaddr addr,
605*e029bb00SHelge Deller                                               uint64_t val, unsigned size,
606*e029bb00SHelge Deller                                               MemTxAttrs attrs)
607*e029bb00SHelge Deller {
608*e029bb00SHelge Deller     AstroState *s = opaque;
609*e029bb00SHelge Deller 
610*e029bb00SHelge Deller     trace_astro_chip_write(addr, size, val);
611*e029bb00SHelge Deller 
612*e029bb00SHelge Deller     switch ((addr >> 3) << 3) {
613*e029bb00SHelge Deller     case 0x0000:        /* ID */
614*e029bb00SHelge Deller         break;
615*e029bb00SHelge Deller     case 0x0008:        /* IOC_CTRL */
616*e029bb00SHelge Deller         val &= 0x0ffffff;
617*e029bb00SHelge Deller         put_val_in_int64(&s->ioc_ctrl, addr, size, val);
618*e029bb00SHelge Deller         break;
619*e029bb00SHelge Deller     case 0x0010:        /* TOC_CLIENT_ID */
620*e029bb00SHelge Deller         break;
621*e029bb00SHelge Deller     case 0x0030:        /* HP-UX 10.20 and 11.11 reads it. No idea. */
622*e029bb00SHelge Deller         break;
623*e029bb00SHelge Deller     case 0x0300 ... 0x03d8 - 1: /* LMMIO_DIRECT0_BASE... */
624*e029bb00SHelge Deller         put_val_in_arrary(s->ioc_ranges, 0x300, addr, size, val);
625*e029bb00SHelge Deller         break;
626*e029bb00SHelge Deller     case 0x10200:
627*e029bb00SHelge Deller     case 0x10220:
628*e029bb00SHelge Deller     case 0x10230:        /* HP-UX 11.11 reads it. No idea. */
629*e029bb00SHelge Deller         break;
630*e029bb00SHelge Deller     case 0x22108:        /* IOC STATUS_CONTROL */
631*e029bb00SHelge Deller         put_val_in_int64(&s->ioc_status_ctrl, addr, size, val);
632*e029bb00SHelge Deller         break;
633*e029bb00SHelge Deller     case 0x20200 ... 0x20240 - 1: /* IOC Rope0_Control ... */
634*e029bb00SHelge Deller         put_val_in_arrary(s->ioc_rope_control, 0x20200, addr, size, val);
635*e029bb00SHelge Deller         break;
636*e029bb00SHelge Deller     case 0x20040:        /* IOC Rope config */
637*e029bb00SHelge Deller         put_val_in_int64(&s->ioc_rope_config, addr, size, val);
638*e029bb00SHelge Deller         break;
639*e029bb00SHelge Deller     case 0x20300:
640*e029bb00SHelge Deller         put_val_in_int64(&s->tlb_ibase, addr, size, val);
641*e029bb00SHelge Deller         break;
642*e029bb00SHelge Deller     case 0x20308:
643*e029bb00SHelge Deller         put_val_in_int64(&s->tlb_imask, addr, size, val);
644*e029bb00SHelge Deller         break;
645*e029bb00SHelge Deller     case 0x20310:
646*e029bb00SHelge Deller         put_val_in_int64(&s->tlb_pcom, addr, size, val);
647*e029bb00SHelge Deller         /* TODO: flush iommu */
648*e029bb00SHelge Deller         break;
649*e029bb00SHelge Deller     case 0x20318:
650*e029bb00SHelge Deller         put_val_in_int64(&s->tlb_tcnfg, addr, size, val);
651*e029bb00SHelge Deller         break;
652*e029bb00SHelge Deller     case 0x20320:
653*e029bb00SHelge Deller         put_val_in_int64(&s->tlb_pdir_base, addr, size, val);
654*e029bb00SHelge Deller         break;
655*e029bb00SHelge Deller     /*
656*e029bb00SHelge Deller      * empty placeholders for non-existent elroys, e.g.
657*e029bb00SHelge Deller      * func_class, pci config & data
658*e029bb00SHelge Deller      */
659*e029bb00SHelge Deller #define EMPTY_PORT(x) case x: case x+8: case x+0x40: case x+0x48:
660*e029bb00SHelge Deller         EMPTY_PORT(0x30000)
661*e029bb00SHelge Deller         EMPTY_PORT(0x32000)
662*e029bb00SHelge Deller         EMPTY_PORT(0x34000)
663*e029bb00SHelge Deller         EMPTY_PORT(0x36000)
664*e029bb00SHelge Deller         EMPTY_PORT(0x38000)
665*e029bb00SHelge Deller         EMPTY_PORT(0x3a000)
666*e029bb00SHelge Deller         EMPTY_PORT(0x3c000)
667*e029bb00SHelge Deller         EMPTY_PORT(0x3e000)
668*e029bb00SHelge Deller         break;
669*e029bb00SHelge Deller #undef EMPTY_PORT
670*e029bb00SHelge Deller 
671*e029bb00SHelge Deller     default:
672*e029bb00SHelge Deller         /* Controlled by astro_chip_mem_valid above.  */
673*e029bb00SHelge Deller         trace_astro_chip_write(addr, size, val);
674*e029bb00SHelge Deller         g_assert_not_reached();
675*e029bb00SHelge Deller     }
676*e029bb00SHelge Deller     return MEMTX_OK;
677*e029bb00SHelge Deller }
678*e029bb00SHelge Deller 
679*e029bb00SHelge Deller static const MemoryRegionOps astro_chip_ops = {
680*e029bb00SHelge Deller     .read_with_attrs = astro_chip_read_with_attrs,
681*e029bb00SHelge Deller     .write_with_attrs = astro_chip_write_with_attrs,
682*e029bb00SHelge Deller     .endianness = DEVICE_LITTLE_ENDIAN,
683*e029bb00SHelge Deller     .valid = {
684*e029bb00SHelge Deller         .min_access_size = 4,
685*e029bb00SHelge Deller         .max_access_size = 8,
686*e029bb00SHelge Deller     },
687*e029bb00SHelge Deller     .impl = {
688*e029bb00SHelge Deller         .min_access_size = 4,
689*e029bb00SHelge Deller         .max_access_size = 8,
690*e029bb00SHelge Deller     },
691*e029bb00SHelge Deller };
692*e029bb00SHelge Deller 
693*e029bb00SHelge Deller static const VMStateDescription vmstate_astro = {
694*e029bb00SHelge Deller     .name = "Astro",
695*e029bb00SHelge Deller     .version_id = 1,
696*e029bb00SHelge Deller     .minimum_version_id = 1,
697*e029bb00SHelge Deller     .fields = (VMStateField[]) {
698*e029bb00SHelge Deller         VMSTATE_UINT64(ioc_ctrl, AstroState),
699*e029bb00SHelge Deller         VMSTATE_UINT64(ioc_status_ctrl, AstroState),
700*e029bb00SHelge Deller         VMSTATE_UINT64_ARRAY(ioc_ranges, AstroState, (0x03d8 - 0x300) / 8),
701*e029bb00SHelge Deller         VMSTATE_UINT64(ioc_rope_config, AstroState),
702*e029bb00SHelge Deller         VMSTATE_UINT64(ioc_status_control, AstroState),
703*e029bb00SHelge Deller         VMSTATE_UINT64(ioc_flush_control, AstroState),
704*e029bb00SHelge Deller         VMSTATE_UINT64_ARRAY(ioc_rope_control, AstroState, 8),
705*e029bb00SHelge Deller         VMSTATE_UINT64(tlb_ibase, AstroState),
706*e029bb00SHelge Deller         VMSTATE_UINT64(tlb_imask, AstroState),
707*e029bb00SHelge Deller         VMSTATE_UINT64(tlb_pcom, AstroState),
708*e029bb00SHelge Deller         VMSTATE_UINT64(tlb_tcnfg, AstroState),
709*e029bb00SHelge Deller         VMSTATE_UINT64(tlb_pdir_base, AstroState),
710*e029bb00SHelge Deller         VMSTATE_END_OF_LIST()
711*e029bb00SHelge Deller     }
712*e029bb00SHelge Deller };
713*e029bb00SHelge Deller 
714*e029bb00SHelge Deller static void astro_reset(DeviceState *dev)
715*e029bb00SHelge Deller {
716*e029bb00SHelge Deller     AstroState *s = ASTRO_CHIP(dev);
717*e029bb00SHelge Deller     int i;
718*e029bb00SHelge Deller 
719*e029bb00SHelge Deller     s->ioc_ctrl = 0x29cf;
720*e029bb00SHelge Deller     s->ioc_rope_config = 0xc5f;
721*e029bb00SHelge Deller     s->ioc_flush_control = 0xb03;
722*e029bb00SHelge Deller     s->ioc_status_control = 0;
723*e029bb00SHelge Deller     memset(&s->ioc_rope_control, 0, sizeof(s->ioc_rope_control));
724*e029bb00SHelge Deller 
725*e029bb00SHelge Deller     /*
726*e029bb00SHelge Deller      * The SBA BASE/MASK registers control CPU -> IO routing.
727*e029bb00SHelge Deller      * The LBA BASE/MASK registers control IO -> System routing (in Elroy)
728*e029bb00SHelge Deller      */
729*e029bb00SHelge Deller     memset(&s->ioc_ranges, 0, sizeof(s->ioc_ranges));
730*e029bb00SHelge Deller     s->ioc_ranges[(0x360 - 0x300) / 8] = LMMIO_DIST_BASE_ADDR | 0x01; /* LMMIO_DIST_BASE (SBA) */
731*e029bb00SHelge Deller     s->ioc_ranges[(0x368 - 0x300) / 8] = 0xfc000000;          /* LMMIO_DIST_MASK */
732*e029bb00SHelge Deller     s->ioc_ranges[(0x370 - 0x300) / 8] = 0;                   /* LMMIO_DIST_ROUTE */
733*e029bb00SHelge Deller     s->ioc_ranges[(0x390 - 0x300) / 8] = IOS_DIST_BASE_ADDR | 0x01; /* IOS_DIST_BASE */
734*e029bb00SHelge Deller     s->ioc_ranges[(0x398 - 0x300) / 8] = 0xffffff0000;        /* IOS_DIST_MASK    */
735*e029bb00SHelge Deller     s->ioc_ranges[(0x3a0 - 0x300) / 8] = 0x3400000000000000ULL; /* IOS_DIST_ROUTE */
736*e029bb00SHelge Deller     s->ioc_ranges[(0x3c0 - 0x300) / 8] = 0xfffee00000;        /* IOS_DIRECT_BASE  */
737*e029bb00SHelge Deller     s->ioc_ranges[(0x3c8 - 0x300) / 8] = 0xffffff0000;        /* IOS_DIRECT_MASK  */
738*e029bb00SHelge Deller     s->ioc_ranges[(0x3d0 - 0x300) / 8] = 0x0;                 /* IOS_DIRECT_ROUTE */
739*e029bb00SHelge Deller 
740*e029bb00SHelge Deller     s->tlb_ibase = 0;
741*e029bb00SHelge Deller     s->tlb_imask = 0;
742*e029bb00SHelge Deller     s->tlb_pcom = 0;
743*e029bb00SHelge Deller     s->tlb_tcnfg = 0;
744*e029bb00SHelge Deller     s->tlb_pdir_base = 0;
745*e029bb00SHelge Deller 
746*e029bb00SHelge Deller     for (i = 0; i < ELROY_NUM; i++) {
747*e029bb00SHelge Deller         elroy_reset(DEVICE(s->elroy[i]));
748*e029bb00SHelge Deller     }
749*e029bb00SHelge Deller }
750*e029bb00SHelge Deller 
751*e029bb00SHelge Deller static void astro_init(Object *obj)
752*e029bb00SHelge Deller {
753*e029bb00SHelge Deller }
754*e029bb00SHelge Deller 
755*e029bb00SHelge Deller static void astro_realize(DeviceState *obj, Error **errp)
756*e029bb00SHelge Deller {
757*e029bb00SHelge Deller     AstroState *s = ASTRO_CHIP(obj);
758*e029bb00SHelge Deller     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
759*e029bb00SHelge Deller     int i;
760*e029bb00SHelge Deller 
761*e029bb00SHelge Deller     memory_region_init_io(&s->this_mem, OBJECT(s), &astro_chip_ops,
762*e029bb00SHelge Deller                           s, "astro", 0x40000);
763*e029bb00SHelge Deller     sysbus_init_mmio(sbd, &s->this_mem);
764*e029bb00SHelge Deller 
765*e029bb00SHelge Deller     /* Host memory as seen from Elroys PCI side, via the IOMMU.  */
766*e029bb00SHelge Deller     memory_region_init_iommu(&s->iommu, sizeof(s->iommu),
767*e029bb00SHelge Deller                              TYPE_ASTRO_IOMMU_MEMORY_REGION, OBJECT(s),
768*e029bb00SHelge Deller                              "iommu-astro", UINT64_MAX);
769*e029bb00SHelge Deller     address_space_init(&s->iommu_as, MEMORY_REGION(&s->iommu),
770*e029bb00SHelge Deller                        "bm-pci");
771*e029bb00SHelge Deller 
772*e029bb00SHelge Deller     /* Create Elroys (PCI host bus chips).  */
773*e029bb00SHelge Deller     for (i = 0; i < ELROY_NUM; i++) {
774*e029bb00SHelge Deller         static const int elroy_hpa_offsets[ELROY_NUM] = {
775*e029bb00SHelge Deller                     0x30000, 0x32000, 0x38000, 0x3c000 };
776*e029bb00SHelge Deller         static const char elroy_rope_nr[ELROY_NUM] = {
777*e029bb00SHelge Deller                     0, 1, 4, 6 }; /* busnum path, e.g. [10:6] */
778*e029bb00SHelge Deller         int addr_offset;
779*e029bb00SHelge Deller         ElroyState *elroy;
780*e029bb00SHelge Deller         hwaddr map_addr;
781*e029bb00SHelge Deller         uint64_t map_size;
782*e029bb00SHelge Deller         int rope;
783*e029bb00SHelge Deller 
784*e029bb00SHelge Deller         addr_offset = elroy_hpa_offsets[i];
785*e029bb00SHelge Deller         rope = elroy_rope_nr[i];
786*e029bb00SHelge Deller 
787*e029bb00SHelge Deller         elroy = elroy_init(i);
788*e029bb00SHelge Deller         s->elroy[i] = elroy;
789*e029bb00SHelge Deller         elroy->hpa = ASTRO_HPA + addr_offset;
790*e029bb00SHelge Deller         elroy->pci_bus_num = i;
791*e029bb00SHelge Deller         elroy->astro = s;
792*e029bb00SHelge Deller 
793*e029bb00SHelge Deller         /*
794*e029bb00SHelge Deller          * NOTE: we only allow PCI devices on first Elroy for now.
795*e029bb00SHelge Deller          * SeaBIOS will not find devices on the other busses.
796*e029bb00SHelge Deller          */
797*e029bb00SHelge Deller         if (i > 0) {
798*e029bb00SHelge Deller             qbus_mark_full(&PCI_HOST_BRIDGE(elroy)->bus->qbus);
799*e029bb00SHelge Deller         }
800*e029bb00SHelge Deller 
801*e029bb00SHelge Deller         /* map elroy config addresses into Astro space */
802*e029bb00SHelge Deller         memory_region_add_subregion(&s->this_mem, addr_offset,
803*e029bb00SHelge Deller                                     &elroy->this_mem);
804*e029bb00SHelge Deller 
805*e029bb00SHelge Deller         /* LMMIO */
806*e029bb00SHelge Deller         elroy->mmio_base[(0x0200 - 0x200) / 8] = 0xf0000001;
807*e029bb00SHelge Deller         elroy->mmio_base[(0x0208 - 0x200) / 8] = 0xf8000000;
808*e029bb00SHelge Deller         /* GMMIO */
809*e029bb00SHelge Deller         elroy->mmio_base[(0x0210 - 0x200) / 8] = 0x000000f800000001;
810*e029bb00SHelge Deller         elroy->mmio_base[(0x0218 - 0x200) / 8] = 0x000000ff80000000;
811*e029bb00SHelge Deller         /* WLMMIO */
812*e029bb00SHelge Deller         elroy->mmio_base[(0x0220 - 0x200) / 8] = 0xf0000001;
813*e029bb00SHelge Deller         elroy->mmio_base[(0x0228 - 0x200) / 8] = 0xf0000000;
814*e029bb00SHelge Deller         /* WGMMIO */
815*e029bb00SHelge Deller         elroy->mmio_base[(0x0230 - 0x200) / 8] = 0x000000f800000001;
816*e029bb00SHelge Deller         elroy->mmio_base[(0x0238 - 0x200) / 8] = 0x000000fc00000000;
817*e029bb00SHelge Deller         /* IOS_BASE */
818*e029bb00SHelge Deller         map_size = IOS_DIST_BASE_SIZE / ROPES_PER_IOC;
819*e029bb00SHelge Deller         elroy->mmio_base[(0x0240 - 0x200) / 8] = rope * map_size | 0x01;
820*e029bb00SHelge Deller         elroy->mmio_base[(0x0248 - 0x200) / 8] = 0x0000e000;
821*e029bb00SHelge Deller 
822*e029bb00SHelge Deller         /* map elroys mmio */
823*e029bb00SHelge Deller         map_size = LMMIO_DIST_BASE_SIZE / ROPES_PER_IOC;
824*e029bb00SHelge Deller         map_addr = (uint32_t) (LMMIO_DIST_BASE_ADDR + rope * map_size);
825*e029bb00SHelge Deller         memory_region_init_alias(&elroy->pci_mmio_alias, OBJECT(elroy),
826*e029bb00SHelge Deller                                  "pci-mmio-alias",
827*e029bb00SHelge Deller                                  &elroy->pci_mmio, map_addr, map_size);
828*e029bb00SHelge Deller         memory_region_add_subregion(get_system_memory(), map_addr,
829*e029bb00SHelge Deller                                  &elroy->pci_mmio_alias);
830*e029bb00SHelge Deller 
831*e029bb00SHelge Deller         map_size = IOS_DIST_BASE_SIZE / ROPES_PER_IOC;
832*e029bb00SHelge Deller         map_addr = (uint32_t) (IOS_DIST_BASE_ADDR + rope * map_size);
833*e029bb00SHelge Deller         memory_region_add_subregion(get_system_memory(), map_addr,
834*e029bb00SHelge Deller                                  &elroy->pci_io);
835*e029bb00SHelge Deller 
836*e029bb00SHelge Deller         /* Host memory as seen from the PCI side, via the IOMMU.  */
837*e029bb00SHelge Deller         pci_setup_iommu(PCI_HOST_BRIDGE(elroy)->bus, elroy_pcihost_set_iommu,
838*e029bb00SHelge Deller                                  elroy);
839*e029bb00SHelge Deller     }
840*e029bb00SHelge Deller }
841*e029bb00SHelge Deller 
842*e029bb00SHelge Deller static void astro_class_init(ObjectClass *klass, void *data)
843*e029bb00SHelge Deller {
844*e029bb00SHelge Deller     DeviceClass *dc = DEVICE_CLASS(klass);
845*e029bb00SHelge Deller 
846*e029bb00SHelge Deller     dc->reset = astro_reset;
847*e029bb00SHelge Deller     dc->vmsd = &vmstate_astro;
848*e029bb00SHelge Deller     dc->realize = astro_realize;
849*e029bb00SHelge Deller     /*
850*e029bb00SHelge Deller      * astro with elroys are hard part of the newer PA2.0 machines and can not
851*e029bb00SHelge Deller      * be created without that hardware
852*e029bb00SHelge Deller      */
853*e029bb00SHelge Deller     dc->user_creatable = false;
854*e029bb00SHelge Deller }
855*e029bb00SHelge Deller 
856*e029bb00SHelge Deller static const TypeInfo astro_chip_info = {
857*e029bb00SHelge Deller     .name          = TYPE_ASTRO_CHIP,
858*e029bb00SHelge Deller     .parent        = TYPE_SYS_BUS_DEVICE,
859*e029bb00SHelge Deller     .instance_init = astro_init,
860*e029bb00SHelge Deller     .instance_size = sizeof(AstroState),
861*e029bb00SHelge Deller     .class_init    = astro_class_init,
862*e029bb00SHelge Deller };
863*e029bb00SHelge Deller 
864*e029bb00SHelge Deller static void astro_iommu_memory_region_class_init(ObjectClass *klass,
865*e029bb00SHelge Deller                                                    void *data)
866*e029bb00SHelge Deller {
867*e029bb00SHelge Deller     IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
868*e029bb00SHelge Deller 
869*e029bb00SHelge Deller     imrc->translate = astro_translate_iommu;
870*e029bb00SHelge Deller }
871*e029bb00SHelge Deller 
872*e029bb00SHelge Deller static const TypeInfo astro_iommu_memory_region_info = {
873*e029bb00SHelge Deller     .parent = TYPE_IOMMU_MEMORY_REGION,
874*e029bb00SHelge Deller     .name = TYPE_ASTRO_IOMMU_MEMORY_REGION,
875*e029bb00SHelge Deller     .class_init = astro_iommu_memory_region_class_init,
876*e029bb00SHelge Deller };
877*e029bb00SHelge Deller 
878*e029bb00SHelge Deller 
879*e029bb00SHelge Deller static void astro_register_types(void)
880*e029bb00SHelge Deller {
881*e029bb00SHelge Deller     type_register_static(&astro_chip_info);
882*e029bb00SHelge Deller     type_register_static(&astro_iommu_memory_region_info);
883*e029bb00SHelge Deller }
884*e029bb00SHelge Deller 
885*e029bb00SHelge Deller type_init(astro_register_types)
886