xref: /openbmc/qemu/hw/misc/djmemc.c (revision 83baec642a13a69398a2643a1f905606c13cd363)
1e2fd695eSMark Cave-Ayland /*
2e2fd695eSMark Cave-Ayland  * djMEMC, macintosh memory and interrupt controller
3e2fd695eSMark Cave-Ayland  * (Quadra 610/650/800 & Centris 610/650)
4e2fd695eSMark Cave-Ayland  *
5e2fd695eSMark Cave-Ayland  *    https://mac68k.info/wiki/display/mac68k/djMEMC+Information
6e2fd695eSMark Cave-Ayland  *
7e2fd695eSMark Cave-Ayland  * SPDX-License-Identifier: GPL-2.0-or-later
8e2fd695eSMark Cave-Ayland  */
9e2fd695eSMark Cave-Ayland 
10e2fd695eSMark Cave-Ayland #include "qemu/osdep.h"
11e2fd695eSMark Cave-Ayland #include "qemu/log.h"
12e2fd695eSMark Cave-Ayland #include "migration/vmstate.h"
13e2fd695eSMark Cave-Ayland #include "hw/misc/djmemc.h"
14e2fd695eSMark Cave-Ayland #include "hw/qdev-properties.h"
15e2fd695eSMark Cave-Ayland #include "trace.h"
16e2fd695eSMark Cave-Ayland 
17e2fd695eSMark Cave-Ayland 
18e2fd695eSMark Cave-Ayland #define DJMEMC_INTERLEAVECONF   0x0
19e2fd695eSMark Cave-Ayland #define DJMEMC_BANK0CONF        0x4
20e2fd695eSMark Cave-Ayland #define DJMEMC_BANK1CONF        0x8
21e2fd695eSMark Cave-Ayland #define DJMEMC_BANK2CONF        0xc
22e2fd695eSMark Cave-Ayland #define DJMEMC_BANK3CONF        0x10
23e2fd695eSMark Cave-Ayland #define DJMEMC_BANK4CONF        0x14
24e2fd695eSMark Cave-Ayland #define DJMEMC_BANK5CONF        0x18
25e2fd695eSMark Cave-Ayland #define DJMEMC_BANK6CONF        0x1c
26e2fd695eSMark Cave-Ayland #define DJMEMC_BANK7CONF        0x20
27e2fd695eSMark Cave-Ayland #define DJMEMC_BANK8CONF        0x24
28e2fd695eSMark Cave-Ayland #define DJMEMC_BANK9CONF        0x28
29e2fd695eSMark Cave-Ayland #define DJMEMC_MEMTOP           0x2c
30e2fd695eSMark Cave-Ayland #define DJMEMC_CONFIG           0x30
31e2fd695eSMark Cave-Ayland #define DJMEMC_REFRESH          0x34
32e2fd695eSMark Cave-Ayland 
33e2fd695eSMark Cave-Ayland 
djmemc_read(void * opaque,hwaddr addr,unsigned size)34e2fd695eSMark Cave-Ayland static uint64_t djmemc_read(void *opaque, hwaddr addr, unsigned size)
35e2fd695eSMark Cave-Ayland {
36e2fd695eSMark Cave-Ayland     DJMEMCState *s = opaque;
37e2fd695eSMark Cave-Ayland     uint64_t val = 0;
38e2fd695eSMark Cave-Ayland 
39e2fd695eSMark Cave-Ayland     switch (addr) {
40e2fd695eSMark Cave-Ayland     case DJMEMC_INTERLEAVECONF:
41e2fd695eSMark Cave-Ayland     case DJMEMC_BANK0CONF ... DJMEMC_BANK9CONF:
42e2fd695eSMark Cave-Ayland     case DJMEMC_MEMTOP:
43e2fd695eSMark Cave-Ayland     case DJMEMC_CONFIG:
44e2fd695eSMark Cave-Ayland     case DJMEMC_REFRESH:
45e2fd695eSMark Cave-Ayland         val = s->regs[addr >> 2];
46e2fd695eSMark Cave-Ayland         break;
47e2fd695eSMark Cave-Ayland     default:
48e2fd695eSMark Cave-Ayland         qemu_log_mask(LOG_UNIMP, "djMEMC: unimplemented read addr=0x%"PRIx64
49e2fd695eSMark Cave-Ayland                                  " val=0x%"PRIx64 " size=%d\n",
50e2fd695eSMark Cave-Ayland                                  addr, val, size);
51e2fd695eSMark Cave-Ayland     }
52e2fd695eSMark Cave-Ayland 
53e2fd695eSMark Cave-Ayland     trace_djmemc_read(addr, val, size);
54e2fd695eSMark Cave-Ayland     return val;
55e2fd695eSMark Cave-Ayland }
56e2fd695eSMark Cave-Ayland 
djmemc_write(void * opaque,hwaddr addr,uint64_t val,unsigned size)57e2fd695eSMark Cave-Ayland static void djmemc_write(void *opaque, hwaddr addr, uint64_t val,
58e2fd695eSMark Cave-Ayland                          unsigned size)
59e2fd695eSMark Cave-Ayland {
60e2fd695eSMark Cave-Ayland     DJMEMCState *s = opaque;
61e2fd695eSMark Cave-Ayland 
62e2fd695eSMark Cave-Ayland     trace_djmemc_write(addr, val, size);
63e2fd695eSMark Cave-Ayland 
64e2fd695eSMark Cave-Ayland     switch (addr) {
65e2fd695eSMark Cave-Ayland     case DJMEMC_INTERLEAVECONF:
66e2fd695eSMark Cave-Ayland     case DJMEMC_BANK0CONF ... DJMEMC_BANK9CONF:
67e2fd695eSMark Cave-Ayland     case DJMEMC_MEMTOP:
68e2fd695eSMark Cave-Ayland     case DJMEMC_CONFIG:
69e2fd695eSMark Cave-Ayland     case DJMEMC_REFRESH:
70e2fd695eSMark Cave-Ayland         s->regs[addr >> 2] = val;
71e2fd695eSMark Cave-Ayland         break;
72e2fd695eSMark Cave-Ayland     default:
73e2fd695eSMark Cave-Ayland         qemu_log_mask(LOG_UNIMP, "djMEMC: unimplemented write addr=0x%"PRIx64
74e2fd695eSMark Cave-Ayland                                  " val=0x%"PRIx64 " size=%d\n",
75e2fd695eSMark Cave-Ayland                                  addr, val, size);
76e2fd695eSMark Cave-Ayland     }
77e2fd695eSMark Cave-Ayland }
78e2fd695eSMark Cave-Ayland 
79e2fd695eSMark Cave-Ayland static const MemoryRegionOps djmemc_mmio_ops = {
80e2fd695eSMark Cave-Ayland     .read = djmemc_read,
81e2fd695eSMark Cave-Ayland     .write = djmemc_write,
82e2fd695eSMark Cave-Ayland     .impl = {
83e2fd695eSMark Cave-Ayland         .min_access_size = 4,
84e2fd695eSMark Cave-Ayland         .max_access_size = 4,
85e2fd695eSMark Cave-Ayland     },
86e2fd695eSMark Cave-Ayland     .endianness = DEVICE_BIG_ENDIAN,
87e2fd695eSMark Cave-Ayland };
88e2fd695eSMark Cave-Ayland 
djmemc_init(Object * obj)89e2fd695eSMark Cave-Ayland static void djmemc_init(Object *obj)
90e2fd695eSMark Cave-Ayland {
91e2fd695eSMark Cave-Ayland     DJMEMCState *s = DJMEMC(obj);
92e2fd695eSMark Cave-Ayland     SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
93e2fd695eSMark Cave-Ayland 
94e2fd695eSMark Cave-Ayland     memory_region_init_io(&s->mem_regs, obj, &djmemc_mmio_ops, s, "djMEMC",
95e2fd695eSMark Cave-Ayland                           DJMEMC_SIZE);
96e2fd695eSMark Cave-Ayland     sysbus_init_mmio(sbd, &s->mem_regs);
97e2fd695eSMark Cave-Ayland }
98e2fd695eSMark Cave-Ayland 
djmemc_reset_hold(Object * obj,ResetType type)99*ad80e367SPeter Maydell static void djmemc_reset_hold(Object *obj, ResetType type)
100e2fd695eSMark Cave-Ayland {
101e2fd695eSMark Cave-Ayland     DJMEMCState *s = DJMEMC(obj);
102e2fd695eSMark Cave-Ayland 
103e2fd695eSMark Cave-Ayland     memset(s->regs, 0, sizeof(s->regs));
104e2fd695eSMark Cave-Ayland }
105e2fd695eSMark Cave-Ayland 
106e2fd695eSMark Cave-Ayland static const VMStateDescription vmstate_djmemc = {
107e2fd695eSMark Cave-Ayland     .name = "djMEMC",
108e2fd695eSMark Cave-Ayland     .version_id = 1,
109e2fd695eSMark Cave-Ayland     .minimum_version_id = 1,
110e4ea952fSRichard Henderson     .fields = (const VMStateField[]) {
111e2fd695eSMark Cave-Ayland         VMSTATE_UINT32_ARRAY(regs, DJMEMCState, DJMEMC_NUM_REGS),
112e2fd695eSMark Cave-Ayland         VMSTATE_END_OF_LIST()
113e2fd695eSMark Cave-Ayland     }
114e2fd695eSMark Cave-Ayland };
115e2fd695eSMark Cave-Ayland 
djmemc_class_init(ObjectClass * oc,void * data)116e2fd695eSMark Cave-Ayland static void djmemc_class_init(ObjectClass *oc, void *data)
117e2fd695eSMark Cave-Ayland {
118e2fd695eSMark Cave-Ayland     DeviceClass *dc = DEVICE_CLASS(oc);
119e2fd695eSMark Cave-Ayland     ResettableClass *rc = RESETTABLE_CLASS(oc);
120e2fd695eSMark Cave-Ayland 
121e2fd695eSMark Cave-Ayland     dc->vmsd = &vmstate_djmemc;
122e2fd695eSMark Cave-Ayland     rc->phases.hold = djmemc_reset_hold;
123e2fd695eSMark Cave-Ayland }
124e2fd695eSMark Cave-Ayland 
125e2fd695eSMark Cave-Ayland static const TypeInfo djmemc_info_types[] = {
126e2fd695eSMark Cave-Ayland     {
127e2fd695eSMark Cave-Ayland         .name          = TYPE_DJMEMC,
128e2fd695eSMark Cave-Ayland         .parent        = TYPE_SYS_BUS_DEVICE,
129e2fd695eSMark Cave-Ayland         .instance_size = sizeof(DJMEMCState),
130e2fd695eSMark Cave-Ayland         .instance_init = djmemc_init,
131e2fd695eSMark Cave-Ayland         .class_init    = djmemc_class_init,
132e2fd695eSMark Cave-Ayland     },
133e2fd695eSMark Cave-Ayland };
134e2fd695eSMark Cave-Ayland 
135e2fd695eSMark Cave-Ayland DEFINE_TYPES(djmemc_info_types)
136