1e28bee8eSPaolo Bonzini /*
2e28bee8eSPaolo Bonzini * QEMU Sparc SLAVIO aux io port emulation
3e28bee8eSPaolo Bonzini *
4e28bee8eSPaolo Bonzini * Copyright (c) 2005 Fabrice Bellard
5e28bee8eSPaolo Bonzini *
6e28bee8eSPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy
7e28bee8eSPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal
8e28bee8eSPaolo Bonzini * in the Software without restriction, including without limitation the rights
9e28bee8eSPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10e28bee8eSPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is
11e28bee8eSPaolo Bonzini * furnished to do so, subject to the following conditions:
12e28bee8eSPaolo Bonzini *
13e28bee8eSPaolo Bonzini * The above copyright notice and this permission notice shall be included in
14e28bee8eSPaolo Bonzini * all copies or substantial portions of the Software.
15e28bee8eSPaolo Bonzini *
16e28bee8eSPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17e28bee8eSPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18e28bee8eSPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19e28bee8eSPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20e28bee8eSPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21e28bee8eSPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22e28bee8eSPaolo Bonzini * THE SOFTWARE.
23e28bee8eSPaolo Bonzini */
24e28bee8eSPaolo Bonzini
250d1c9782SPeter Maydell #include "qemu/osdep.h"
2664552b6bSMarkus Armbruster #include "hw/irq.h"
27e28bee8eSPaolo Bonzini #include "hw/sysbus.h"
28d6454270SMarkus Armbruster #include "migration/vmstate.h"
290b8fa32fSMarkus Armbruster #include "qemu/module.h"
3054d31236SMarkus Armbruster #include "sysemu/runstate.h"
31e28bee8eSPaolo Bonzini #include "trace.h"
32db1015e9SEduardo Habkost #include "qom/object.h"
33e28bee8eSPaolo Bonzini
34e28bee8eSPaolo Bonzini /*
35e28bee8eSPaolo Bonzini * This is the auxio port, chip control and system control part of
36e28bee8eSPaolo Bonzini * chip STP2001 (Slave I/O), also produced as NCR89C105. See
37e28bee8eSPaolo Bonzini * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C105.txt
38e28bee8eSPaolo Bonzini *
39e28bee8eSPaolo Bonzini * This also includes the PMC CPU idle controller.
40e28bee8eSPaolo Bonzini */
41e28bee8eSPaolo Bonzini
4295eb2084SAndreas Färber #define TYPE_SLAVIO_MISC "slavio_misc"
438063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(MiscState, SLAVIO_MISC)
4495eb2084SAndreas Färber
45db1015e9SEduardo Habkost struct MiscState {
4695eb2084SAndreas Färber SysBusDevice parent_obj;
4795eb2084SAndreas Färber
48e28bee8eSPaolo Bonzini MemoryRegion cfg_iomem;
49e28bee8eSPaolo Bonzini MemoryRegion diag_iomem;
50e28bee8eSPaolo Bonzini MemoryRegion mdm_iomem;
51e28bee8eSPaolo Bonzini MemoryRegion led_iomem;
52e28bee8eSPaolo Bonzini MemoryRegion sysctrl_iomem;
53e28bee8eSPaolo Bonzini MemoryRegion aux1_iomem;
54e28bee8eSPaolo Bonzini MemoryRegion aux2_iomem;
55e28bee8eSPaolo Bonzini qemu_irq irq;
56e28bee8eSPaolo Bonzini qemu_irq fdc_tc;
57e28bee8eSPaolo Bonzini uint32_t dummy;
58e28bee8eSPaolo Bonzini uint8_t config;
59e28bee8eSPaolo Bonzini uint8_t aux1, aux2;
60e28bee8eSPaolo Bonzini uint8_t diag, mctrl;
61e28bee8eSPaolo Bonzini uint8_t sysctrl;
62e28bee8eSPaolo Bonzini uint16_t leds;
63db1015e9SEduardo Habkost };
64e28bee8eSPaolo Bonzini
65f1a0a79fSAndreas Färber #define TYPE_APC "apc"
66db1015e9SEduardo Habkost typedef struct APCState APCState;
678110fa1dSEduardo Habkost DECLARE_INSTANCE_CHECKER(APCState, APC,
688110fa1dSEduardo Habkost TYPE_APC)
69f1a0a79fSAndreas Färber
70db1015e9SEduardo Habkost struct APCState {
71f1a0a79fSAndreas Färber SysBusDevice parent_obj;
72f1a0a79fSAndreas Färber
73e28bee8eSPaolo Bonzini MemoryRegion iomem;
74e28bee8eSPaolo Bonzini qemu_irq cpu_halt;
75db1015e9SEduardo Habkost };
76e28bee8eSPaolo Bonzini
77e28bee8eSPaolo Bonzini #define MISC_SIZE 1
780e1cd657SMark Cave-Ayland #define LED_SIZE 2
79e28bee8eSPaolo Bonzini #define SYSCTRL_SIZE 4
80e28bee8eSPaolo Bonzini
81e28bee8eSPaolo Bonzini #define AUX1_TC 0x02
82e28bee8eSPaolo Bonzini
83e28bee8eSPaolo Bonzini #define AUX2_PWROFF 0x01
84e28bee8eSPaolo Bonzini #define AUX2_PWRINTCLR 0x02
85e28bee8eSPaolo Bonzini #define AUX2_PWRFAIL 0x20
86e28bee8eSPaolo Bonzini
87e28bee8eSPaolo Bonzini #define CFG_PWRINTEN 0x08
88e28bee8eSPaolo Bonzini
89e28bee8eSPaolo Bonzini #define SYS_RESET 0x01
90e28bee8eSPaolo Bonzini #define SYS_RESETSTAT 0x02
91e28bee8eSPaolo Bonzini
slavio_misc_update_irq(void * opaque)92e28bee8eSPaolo Bonzini static void slavio_misc_update_irq(void *opaque)
93e28bee8eSPaolo Bonzini {
94e28bee8eSPaolo Bonzini MiscState *s = opaque;
95e28bee8eSPaolo Bonzini
96e28bee8eSPaolo Bonzini if ((s->aux2 & AUX2_PWRFAIL) && (s->config & CFG_PWRINTEN)) {
97e28bee8eSPaolo Bonzini trace_slavio_misc_update_irq_raise();
98e28bee8eSPaolo Bonzini qemu_irq_raise(s->irq);
99e28bee8eSPaolo Bonzini } else {
100e28bee8eSPaolo Bonzini trace_slavio_misc_update_irq_lower();
101e28bee8eSPaolo Bonzini qemu_irq_lower(s->irq);
102e28bee8eSPaolo Bonzini }
103e28bee8eSPaolo Bonzini }
104e28bee8eSPaolo Bonzini
slavio_misc_reset(DeviceState * d)105e28bee8eSPaolo Bonzini static void slavio_misc_reset(DeviceState *d)
106e28bee8eSPaolo Bonzini {
10795eb2084SAndreas Färber MiscState *s = SLAVIO_MISC(d);
108e28bee8eSPaolo Bonzini
109e28bee8eSPaolo Bonzini // Diagnostic and system control registers not cleared in reset
110e28bee8eSPaolo Bonzini s->config = s->aux1 = s->aux2 = s->mctrl = 0;
111e28bee8eSPaolo Bonzini }
112e28bee8eSPaolo Bonzini
slavio_set_power_fail(void * opaque,int irq,int power_failing)113e28bee8eSPaolo Bonzini static void slavio_set_power_fail(void *opaque, int irq, int power_failing)
114e28bee8eSPaolo Bonzini {
115e28bee8eSPaolo Bonzini MiscState *s = opaque;
116e28bee8eSPaolo Bonzini
117e28bee8eSPaolo Bonzini trace_slavio_set_power_fail(power_failing, s->config);
118e28bee8eSPaolo Bonzini if (power_failing && (s->config & CFG_PWRINTEN)) {
119e28bee8eSPaolo Bonzini s->aux2 |= AUX2_PWRFAIL;
120e28bee8eSPaolo Bonzini } else {
121e28bee8eSPaolo Bonzini s->aux2 &= ~AUX2_PWRFAIL;
122e28bee8eSPaolo Bonzini }
123e28bee8eSPaolo Bonzini slavio_misc_update_irq(s);
124e28bee8eSPaolo Bonzini }
125e28bee8eSPaolo Bonzini
slavio_cfg_mem_writeb(void * opaque,hwaddr addr,uint64_t val,unsigned size)126e28bee8eSPaolo Bonzini static void slavio_cfg_mem_writeb(void *opaque, hwaddr addr,
127e28bee8eSPaolo Bonzini uint64_t val, unsigned size)
128e28bee8eSPaolo Bonzini {
129e28bee8eSPaolo Bonzini MiscState *s = opaque;
130e28bee8eSPaolo Bonzini
131e28bee8eSPaolo Bonzini trace_slavio_cfg_mem_writeb(val & 0xff);
132e28bee8eSPaolo Bonzini s->config = val & 0xff;
133e28bee8eSPaolo Bonzini slavio_misc_update_irq(s);
134e28bee8eSPaolo Bonzini }
135e28bee8eSPaolo Bonzini
slavio_cfg_mem_readb(void * opaque,hwaddr addr,unsigned size)136e28bee8eSPaolo Bonzini static uint64_t slavio_cfg_mem_readb(void *opaque, hwaddr addr,
137e28bee8eSPaolo Bonzini unsigned size)
138e28bee8eSPaolo Bonzini {
139e28bee8eSPaolo Bonzini MiscState *s = opaque;
140e28bee8eSPaolo Bonzini uint32_t ret = 0;
141e28bee8eSPaolo Bonzini
142e28bee8eSPaolo Bonzini ret = s->config;
143e28bee8eSPaolo Bonzini trace_slavio_cfg_mem_readb(ret);
144e28bee8eSPaolo Bonzini return ret;
145e28bee8eSPaolo Bonzini }
146e28bee8eSPaolo Bonzini
147e28bee8eSPaolo Bonzini static const MemoryRegionOps slavio_cfg_mem_ops = {
148e28bee8eSPaolo Bonzini .read = slavio_cfg_mem_readb,
149e28bee8eSPaolo Bonzini .write = slavio_cfg_mem_writeb,
150e28bee8eSPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN,
151e28bee8eSPaolo Bonzini .valid = {
152e28bee8eSPaolo Bonzini .min_access_size = 1,
153e28bee8eSPaolo Bonzini .max_access_size = 1,
154e28bee8eSPaolo Bonzini },
155e28bee8eSPaolo Bonzini };
156e28bee8eSPaolo Bonzini
slavio_diag_mem_writeb(void * opaque,hwaddr addr,uint64_t val,unsigned size)157e28bee8eSPaolo Bonzini static void slavio_diag_mem_writeb(void *opaque, hwaddr addr,
158e28bee8eSPaolo Bonzini uint64_t val, unsigned size)
159e28bee8eSPaolo Bonzini {
160e28bee8eSPaolo Bonzini MiscState *s = opaque;
161e28bee8eSPaolo Bonzini
162e28bee8eSPaolo Bonzini trace_slavio_diag_mem_writeb(val & 0xff);
163e28bee8eSPaolo Bonzini s->diag = val & 0xff;
164e28bee8eSPaolo Bonzini }
165e28bee8eSPaolo Bonzini
slavio_diag_mem_readb(void * opaque,hwaddr addr,unsigned size)166e28bee8eSPaolo Bonzini static uint64_t slavio_diag_mem_readb(void *opaque, hwaddr addr,
167e28bee8eSPaolo Bonzini unsigned size)
168e28bee8eSPaolo Bonzini {
169e28bee8eSPaolo Bonzini MiscState *s = opaque;
170e28bee8eSPaolo Bonzini uint32_t ret = 0;
171e28bee8eSPaolo Bonzini
172e28bee8eSPaolo Bonzini ret = s->diag;
173e28bee8eSPaolo Bonzini trace_slavio_diag_mem_readb(ret);
174e28bee8eSPaolo Bonzini return ret;
175e28bee8eSPaolo Bonzini }
176e28bee8eSPaolo Bonzini
177e28bee8eSPaolo Bonzini static const MemoryRegionOps slavio_diag_mem_ops = {
178e28bee8eSPaolo Bonzini .read = slavio_diag_mem_readb,
179e28bee8eSPaolo Bonzini .write = slavio_diag_mem_writeb,
180e28bee8eSPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN,
181e28bee8eSPaolo Bonzini .valid = {
182e28bee8eSPaolo Bonzini .min_access_size = 1,
183e28bee8eSPaolo Bonzini .max_access_size = 1,
184e28bee8eSPaolo Bonzini },
185e28bee8eSPaolo Bonzini };
186e28bee8eSPaolo Bonzini
slavio_mdm_mem_writeb(void * opaque,hwaddr addr,uint64_t val,unsigned size)187e28bee8eSPaolo Bonzini static void slavio_mdm_mem_writeb(void *opaque, hwaddr addr,
188e28bee8eSPaolo Bonzini uint64_t val, unsigned size)
189e28bee8eSPaolo Bonzini {
190e28bee8eSPaolo Bonzini MiscState *s = opaque;
191e28bee8eSPaolo Bonzini
192e28bee8eSPaolo Bonzini trace_slavio_mdm_mem_writeb(val & 0xff);
193e28bee8eSPaolo Bonzini s->mctrl = val & 0xff;
194e28bee8eSPaolo Bonzini }
195e28bee8eSPaolo Bonzini
slavio_mdm_mem_readb(void * opaque,hwaddr addr,unsigned size)196e28bee8eSPaolo Bonzini static uint64_t slavio_mdm_mem_readb(void *opaque, hwaddr addr,
197e28bee8eSPaolo Bonzini unsigned size)
198e28bee8eSPaolo Bonzini {
199e28bee8eSPaolo Bonzini MiscState *s = opaque;
200e28bee8eSPaolo Bonzini uint32_t ret = 0;
201e28bee8eSPaolo Bonzini
202e28bee8eSPaolo Bonzini ret = s->mctrl;
203e28bee8eSPaolo Bonzini trace_slavio_mdm_mem_readb(ret);
204e28bee8eSPaolo Bonzini return ret;
205e28bee8eSPaolo Bonzini }
206e28bee8eSPaolo Bonzini
207e28bee8eSPaolo Bonzini static const MemoryRegionOps slavio_mdm_mem_ops = {
208e28bee8eSPaolo Bonzini .read = slavio_mdm_mem_readb,
209e28bee8eSPaolo Bonzini .write = slavio_mdm_mem_writeb,
210e28bee8eSPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN,
211e28bee8eSPaolo Bonzini .valid = {
212e28bee8eSPaolo Bonzini .min_access_size = 1,
213e28bee8eSPaolo Bonzini .max_access_size = 1,
214e28bee8eSPaolo Bonzini },
215e28bee8eSPaolo Bonzini };
216e28bee8eSPaolo Bonzini
slavio_aux1_mem_writeb(void * opaque,hwaddr addr,uint64_t val,unsigned size)217e28bee8eSPaolo Bonzini static void slavio_aux1_mem_writeb(void *opaque, hwaddr addr,
218e28bee8eSPaolo Bonzini uint64_t val, unsigned size)
219e28bee8eSPaolo Bonzini {
220e28bee8eSPaolo Bonzini MiscState *s = opaque;
221e28bee8eSPaolo Bonzini
222e28bee8eSPaolo Bonzini trace_slavio_aux1_mem_writeb(val & 0xff);
223e28bee8eSPaolo Bonzini if (val & AUX1_TC) {
224e28bee8eSPaolo Bonzini // Send a pulse to floppy terminal count line
225e28bee8eSPaolo Bonzini if (s->fdc_tc) {
226e28bee8eSPaolo Bonzini qemu_irq_raise(s->fdc_tc);
227e28bee8eSPaolo Bonzini qemu_irq_lower(s->fdc_tc);
228e28bee8eSPaolo Bonzini }
229e28bee8eSPaolo Bonzini val &= ~AUX1_TC;
230e28bee8eSPaolo Bonzini }
231e28bee8eSPaolo Bonzini s->aux1 = val & 0xff;
232e28bee8eSPaolo Bonzini }
233e28bee8eSPaolo Bonzini
slavio_aux1_mem_readb(void * opaque,hwaddr addr,unsigned size)234e28bee8eSPaolo Bonzini static uint64_t slavio_aux1_mem_readb(void *opaque, hwaddr addr,
235e28bee8eSPaolo Bonzini unsigned size)
236e28bee8eSPaolo Bonzini {
237e28bee8eSPaolo Bonzini MiscState *s = opaque;
238e28bee8eSPaolo Bonzini uint32_t ret = 0;
239e28bee8eSPaolo Bonzini
240e28bee8eSPaolo Bonzini ret = s->aux1;
241e28bee8eSPaolo Bonzini trace_slavio_aux1_mem_readb(ret);
242e28bee8eSPaolo Bonzini return ret;
243e28bee8eSPaolo Bonzini }
244e28bee8eSPaolo Bonzini
245e28bee8eSPaolo Bonzini static const MemoryRegionOps slavio_aux1_mem_ops = {
246e28bee8eSPaolo Bonzini .read = slavio_aux1_mem_readb,
247e28bee8eSPaolo Bonzini .write = slavio_aux1_mem_writeb,
248e28bee8eSPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN,
249e28bee8eSPaolo Bonzini .valid = {
250e28bee8eSPaolo Bonzini .min_access_size = 1,
251e28bee8eSPaolo Bonzini .max_access_size = 1,
252e28bee8eSPaolo Bonzini },
253e28bee8eSPaolo Bonzini };
254e28bee8eSPaolo Bonzini
slavio_aux2_mem_writeb(void * opaque,hwaddr addr,uint64_t val,unsigned size)255e28bee8eSPaolo Bonzini static void slavio_aux2_mem_writeb(void *opaque, hwaddr addr,
256e28bee8eSPaolo Bonzini uint64_t val, unsigned size)
257e28bee8eSPaolo Bonzini {
258e28bee8eSPaolo Bonzini MiscState *s = opaque;
259e28bee8eSPaolo Bonzini
260e28bee8eSPaolo Bonzini val &= AUX2_PWRINTCLR | AUX2_PWROFF;
261e28bee8eSPaolo Bonzini trace_slavio_aux2_mem_writeb(val & 0xff);
262e28bee8eSPaolo Bonzini val |= s->aux2 & AUX2_PWRFAIL;
263e28bee8eSPaolo Bonzini if (val & AUX2_PWRINTCLR) // Clear Power Fail int
264e28bee8eSPaolo Bonzini val &= AUX2_PWROFF;
265e28bee8eSPaolo Bonzini s->aux2 = val;
266e28bee8eSPaolo Bonzini if (val & AUX2_PWROFF)
267cf83f140SEric Blake qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
268e28bee8eSPaolo Bonzini slavio_misc_update_irq(s);
269e28bee8eSPaolo Bonzini }
270e28bee8eSPaolo Bonzini
slavio_aux2_mem_readb(void * opaque,hwaddr addr,unsigned size)271e28bee8eSPaolo Bonzini static uint64_t slavio_aux2_mem_readb(void *opaque, hwaddr addr,
272e28bee8eSPaolo Bonzini unsigned size)
273e28bee8eSPaolo Bonzini {
274e28bee8eSPaolo Bonzini MiscState *s = opaque;
275e28bee8eSPaolo Bonzini uint32_t ret = 0;
276e28bee8eSPaolo Bonzini
277e28bee8eSPaolo Bonzini ret = s->aux2;
278e28bee8eSPaolo Bonzini trace_slavio_aux2_mem_readb(ret);
279e28bee8eSPaolo Bonzini return ret;
280e28bee8eSPaolo Bonzini }
281e28bee8eSPaolo Bonzini
282e28bee8eSPaolo Bonzini static const MemoryRegionOps slavio_aux2_mem_ops = {
283e28bee8eSPaolo Bonzini .read = slavio_aux2_mem_readb,
284e28bee8eSPaolo Bonzini .write = slavio_aux2_mem_writeb,
285e28bee8eSPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN,
286e28bee8eSPaolo Bonzini .valid = {
287e28bee8eSPaolo Bonzini .min_access_size = 1,
288e28bee8eSPaolo Bonzini .max_access_size = 1,
289e28bee8eSPaolo Bonzini },
290e28bee8eSPaolo Bonzini };
291e28bee8eSPaolo Bonzini
apc_mem_writeb(void * opaque,hwaddr addr,uint64_t val,unsigned size)292e28bee8eSPaolo Bonzini static void apc_mem_writeb(void *opaque, hwaddr addr,
293e28bee8eSPaolo Bonzini uint64_t val, unsigned size)
294e28bee8eSPaolo Bonzini {
295e28bee8eSPaolo Bonzini APCState *s = opaque;
296e28bee8eSPaolo Bonzini
297e28bee8eSPaolo Bonzini trace_apc_mem_writeb(val & 0xff);
298e28bee8eSPaolo Bonzini qemu_irq_raise(s->cpu_halt);
299e28bee8eSPaolo Bonzini }
300e28bee8eSPaolo Bonzini
apc_mem_readb(void * opaque,hwaddr addr,unsigned size)301e28bee8eSPaolo Bonzini static uint64_t apc_mem_readb(void *opaque, hwaddr addr,
302e28bee8eSPaolo Bonzini unsigned size)
303e28bee8eSPaolo Bonzini {
304e28bee8eSPaolo Bonzini uint32_t ret = 0;
305e28bee8eSPaolo Bonzini
306e28bee8eSPaolo Bonzini trace_apc_mem_readb(ret);
307e28bee8eSPaolo Bonzini return ret;
308e28bee8eSPaolo Bonzini }
309e28bee8eSPaolo Bonzini
310e28bee8eSPaolo Bonzini static const MemoryRegionOps apc_mem_ops = {
311e28bee8eSPaolo Bonzini .read = apc_mem_readb,
312e28bee8eSPaolo Bonzini .write = apc_mem_writeb,
313e28bee8eSPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN,
314e28bee8eSPaolo Bonzini .valid = {
315e28bee8eSPaolo Bonzini .min_access_size = 1,
316e28bee8eSPaolo Bonzini .max_access_size = 1,
317e28bee8eSPaolo Bonzini }
318e28bee8eSPaolo Bonzini };
319e28bee8eSPaolo Bonzini
slavio_sysctrl_mem_readl(void * opaque,hwaddr addr,unsigned size)320e28bee8eSPaolo Bonzini static uint64_t slavio_sysctrl_mem_readl(void *opaque, hwaddr addr,
321e28bee8eSPaolo Bonzini unsigned size)
322e28bee8eSPaolo Bonzini {
323e28bee8eSPaolo Bonzini MiscState *s = opaque;
324e28bee8eSPaolo Bonzini uint32_t ret = 0;
325e28bee8eSPaolo Bonzini
326e28bee8eSPaolo Bonzini switch (addr) {
327e28bee8eSPaolo Bonzini case 0:
328e28bee8eSPaolo Bonzini ret = s->sysctrl;
329e28bee8eSPaolo Bonzini break;
330e28bee8eSPaolo Bonzini default:
331e28bee8eSPaolo Bonzini break;
332e28bee8eSPaolo Bonzini }
333e28bee8eSPaolo Bonzini trace_slavio_sysctrl_mem_readl(ret);
334e28bee8eSPaolo Bonzini return ret;
335e28bee8eSPaolo Bonzini }
336e28bee8eSPaolo Bonzini
slavio_sysctrl_mem_writel(void * opaque,hwaddr addr,uint64_t val,unsigned size)337e28bee8eSPaolo Bonzini static void slavio_sysctrl_mem_writel(void *opaque, hwaddr addr,
338e28bee8eSPaolo Bonzini uint64_t val, unsigned size)
339e28bee8eSPaolo Bonzini {
340e28bee8eSPaolo Bonzini MiscState *s = opaque;
341e28bee8eSPaolo Bonzini
342e28bee8eSPaolo Bonzini trace_slavio_sysctrl_mem_writel(val);
343e28bee8eSPaolo Bonzini switch (addr) {
344e28bee8eSPaolo Bonzini case 0:
345e28bee8eSPaolo Bonzini if (val & SYS_RESET) {
346e28bee8eSPaolo Bonzini s->sysctrl = SYS_RESETSTAT;
347cf83f140SEric Blake qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
348e28bee8eSPaolo Bonzini }
349e28bee8eSPaolo Bonzini break;
350e28bee8eSPaolo Bonzini default:
351e28bee8eSPaolo Bonzini break;
352e28bee8eSPaolo Bonzini }
353e28bee8eSPaolo Bonzini }
354e28bee8eSPaolo Bonzini
355e28bee8eSPaolo Bonzini static const MemoryRegionOps slavio_sysctrl_mem_ops = {
356e28bee8eSPaolo Bonzini .read = slavio_sysctrl_mem_readl,
357e28bee8eSPaolo Bonzini .write = slavio_sysctrl_mem_writel,
358e28bee8eSPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN,
359e28bee8eSPaolo Bonzini .valid = {
360e28bee8eSPaolo Bonzini .min_access_size = 4,
361e28bee8eSPaolo Bonzini .max_access_size = 4,
362e28bee8eSPaolo Bonzini },
363e28bee8eSPaolo Bonzini };
364e28bee8eSPaolo Bonzini
slavio_led_mem_readw(void * opaque,hwaddr addr,unsigned size)365e28bee8eSPaolo Bonzini static uint64_t slavio_led_mem_readw(void *opaque, hwaddr addr,
366e28bee8eSPaolo Bonzini unsigned size)
367e28bee8eSPaolo Bonzini {
368e28bee8eSPaolo Bonzini MiscState *s = opaque;
369e28bee8eSPaolo Bonzini uint32_t ret = 0;
370e28bee8eSPaolo Bonzini
371e28bee8eSPaolo Bonzini switch (addr) {
372e28bee8eSPaolo Bonzini case 0:
373e28bee8eSPaolo Bonzini ret = s->leds;
374e28bee8eSPaolo Bonzini break;
375e28bee8eSPaolo Bonzini default:
376e28bee8eSPaolo Bonzini break;
377e28bee8eSPaolo Bonzini }
378e28bee8eSPaolo Bonzini trace_slavio_led_mem_readw(ret);
379e28bee8eSPaolo Bonzini return ret;
380e28bee8eSPaolo Bonzini }
381e28bee8eSPaolo Bonzini
slavio_led_mem_writew(void * opaque,hwaddr addr,uint64_t val,unsigned size)382e28bee8eSPaolo Bonzini static void slavio_led_mem_writew(void *opaque, hwaddr addr,
383e28bee8eSPaolo Bonzini uint64_t val, unsigned size)
384e28bee8eSPaolo Bonzini {
385e28bee8eSPaolo Bonzini MiscState *s = opaque;
386e28bee8eSPaolo Bonzini
387f3a64b8cSMarkus Armbruster trace_slavio_led_mem_writew(val & 0xffff);
388e28bee8eSPaolo Bonzini switch (addr) {
389e28bee8eSPaolo Bonzini case 0:
390e28bee8eSPaolo Bonzini s->leds = val;
391e28bee8eSPaolo Bonzini break;
392e28bee8eSPaolo Bonzini default:
393e28bee8eSPaolo Bonzini break;
394e28bee8eSPaolo Bonzini }
395e28bee8eSPaolo Bonzini }
396e28bee8eSPaolo Bonzini
397e28bee8eSPaolo Bonzini static const MemoryRegionOps slavio_led_mem_ops = {
398e28bee8eSPaolo Bonzini .read = slavio_led_mem_readw,
399e28bee8eSPaolo Bonzini .write = slavio_led_mem_writew,
400e28bee8eSPaolo Bonzini .endianness = DEVICE_NATIVE_ENDIAN,
401e28bee8eSPaolo Bonzini .valid = {
402e28bee8eSPaolo Bonzini .min_access_size = 2,
403e28bee8eSPaolo Bonzini .max_access_size = 2,
404e28bee8eSPaolo Bonzini },
405e28bee8eSPaolo Bonzini };
406e28bee8eSPaolo Bonzini
407e28bee8eSPaolo Bonzini static const VMStateDescription vmstate_misc = {
408e28bee8eSPaolo Bonzini .name ="slavio_misc",
409e28bee8eSPaolo Bonzini .version_id = 1,
410e28bee8eSPaolo Bonzini .minimum_version_id = 1,
411e4ea952fSRichard Henderson .fields = (const VMStateField[]) {
412e28bee8eSPaolo Bonzini VMSTATE_UINT32(dummy, MiscState),
413e28bee8eSPaolo Bonzini VMSTATE_UINT8(config, MiscState),
414e28bee8eSPaolo Bonzini VMSTATE_UINT8(aux1, MiscState),
415e28bee8eSPaolo Bonzini VMSTATE_UINT8(aux2, MiscState),
416e28bee8eSPaolo Bonzini VMSTATE_UINT8(diag, MiscState),
417e28bee8eSPaolo Bonzini VMSTATE_UINT8(mctrl, MiscState),
418e28bee8eSPaolo Bonzini VMSTATE_UINT8(sysctrl, MiscState),
419e28bee8eSPaolo Bonzini VMSTATE_END_OF_LIST()
420e28bee8eSPaolo Bonzini }
421e28bee8eSPaolo Bonzini };
422e28bee8eSPaolo Bonzini
apc_init(Object * obj)42346eedc0eSxiaoqiang zhao static void apc_init(Object *obj)
424e28bee8eSPaolo Bonzini {
42546eedc0eSxiaoqiang zhao APCState *s = APC(obj);
42646eedc0eSxiaoqiang zhao SysBusDevice *dev = SYS_BUS_DEVICE(obj);
427e28bee8eSPaolo Bonzini
428e28bee8eSPaolo Bonzini sysbus_init_irq(dev, &s->cpu_halt);
429e28bee8eSPaolo Bonzini
430e28bee8eSPaolo Bonzini /* Power management (APC) XXX: not a Slavio device */
43146eedc0eSxiaoqiang zhao memory_region_init_io(&s->iomem, obj, &apc_mem_ops, s,
432e28bee8eSPaolo Bonzini "apc", MISC_SIZE);
433e28bee8eSPaolo Bonzini sysbus_init_mmio(dev, &s->iomem);
434e28bee8eSPaolo Bonzini }
435e28bee8eSPaolo Bonzini
slavio_misc_init(Object * obj)43646eedc0eSxiaoqiang zhao static void slavio_misc_init(Object *obj)
437e28bee8eSPaolo Bonzini {
43846eedc0eSxiaoqiang zhao DeviceState *dev = DEVICE(obj);
43946eedc0eSxiaoqiang zhao MiscState *s = SLAVIO_MISC(obj);
44046eedc0eSxiaoqiang zhao SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
441e28bee8eSPaolo Bonzini
44295eb2084SAndreas Färber sysbus_init_irq(sbd, &s->irq);
44395eb2084SAndreas Färber sysbus_init_irq(sbd, &s->fdc_tc);
444e28bee8eSPaolo Bonzini
445e28bee8eSPaolo Bonzini /* 8 bit registers */
446e28bee8eSPaolo Bonzini /* Slavio control */
44746eedc0eSxiaoqiang zhao memory_region_init_io(&s->cfg_iomem, obj, &slavio_cfg_mem_ops, s,
448e28bee8eSPaolo Bonzini "configuration", MISC_SIZE);
44995eb2084SAndreas Färber sysbus_init_mmio(sbd, &s->cfg_iomem);
450e28bee8eSPaolo Bonzini
451e28bee8eSPaolo Bonzini /* Diagnostics */
45246eedc0eSxiaoqiang zhao memory_region_init_io(&s->diag_iomem, obj, &slavio_diag_mem_ops, s,
453e28bee8eSPaolo Bonzini "diagnostic", MISC_SIZE);
45495eb2084SAndreas Färber sysbus_init_mmio(sbd, &s->diag_iomem);
455e28bee8eSPaolo Bonzini
456e28bee8eSPaolo Bonzini /* Modem control */
45746eedc0eSxiaoqiang zhao memory_region_init_io(&s->mdm_iomem, obj, &slavio_mdm_mem_ops, s,
458e28bee8eSPaolo Bonzini "modem", MISC_SIZE);
45995eb2084SAndreas Färber sysbus_init_mmio(sbd, &s->mdm_iomem);
460e28bee8eSPaolo Bonzini
461e28bee8eSPaolo Bonzini /* 16 bit registers */
462e28bee8eSPaolo Bonzini /* ss600mp diag LEDs */
46346eedc0eSxiaoqiang zhao memory_region_init_io(&s->led_iomem, obj, &slavio_led_mem_ops, s,
4640e1cd657SMark Cave-Ayland "leds", LED_SIZE);
46595eb2084SAndreas Färber sysbus_init_mmio(sbd, &s->led_iomem);
466e28bee8eSPaolo Bonzini
467e28bee8eSPaolo Bonzini /* 32 bit registers */
468e28bee8eSPaolo Bonzini /* System control */
46946eedc0eSxiaoqiang zhao memory_region_init_io(&s->sysctrl_iomem, obj, &slavio_sysctrl_mem_ops, s,
4700e1cd657SMark Cave-Ayland "system-control", SYSCTRL_SIZE);
47195eb2084SAndreas Färber sysbus_init_mmio(sbd, &s->sysctrl_iomem);
472e28bee8eSPaolo Bonzini
473e28bee8eSPaolo Bonzini /* AUX 1 (Misc System Functions) */
47446eedc0eSxiaoqiang zhao memory_region_init_io(&s->aux1_iomem, obj, &slavio_aux1_mem_ops, s,
475e28bee8eSPaolo Bonzini "misc-system-functions", MISC_SIZE);
47695eb2084SAndreas Färber sysbus_init_mmio(sbd, &s->aux1_iomem);
477e28bee8eSPaolo Bonzini
478e28bee8eSPaolo Bonzini /* AUX 2 (Software Powerdown Control) */
47946eedc0eSxiaoqiang zhao memory_region_init_io(&s->aux2_iomem, obj, &slavio_aux2_mem_ops, s,
480e28bee8eSPaolo Bonzini "software-powerdown-control", MISC_SIZE);
48195eb2084SAndreas Färber sysbus_init_mmio(sbd, &s->aux2_iomem);
482e28bee8eSPaolo Bonzini
48395eb2084SAndreas Färber qdev_init_gpio_in(dev, slavio_set_power_fail, 1);
484e28bee8eSPaolo Bonzini }
485e28bee8eSPaolo Bonzini
slavio_misc_class_init(ObjectClass * klass,void * data)486e28bee8eSPaolo Bonzini static void slavio_misc_class_init(ObjectClass *klass, void *data)
487e28bee8eSPaolo Bonzini {
488e28bee8eSPaolo Bonzini DeviceClass *dc = DEVICE_CLASS(klass);
489e28bee8eSPaolo Bonzini
490*e3d08143SPeter Maydell device_class_set_legacy_reset(dc, slavio_misc_reset);
491e28bee8eSPaolo Bonzini dc->vmsd = &vmstate_misc;
492e28bee8eSPaolo Bonzini }
493e28bee8eSPaolo Bonzini
494e28bee8eSPaolo Bonzini static const TypeInfo slavio_misc_info = {
49595eb2084SAndreas Färber .name = TYPE_SLAVIO_MISC,
496e28bee8eSPaolo Bonzini .parent = TYPE_SYS_BUS_DEVICE,
497e28bee8eSPaolo Bonzini .instance_size = sizeof(MiscState),
49846eedc0eSxiaoqiang zhao .instance_init = slavio_misc_init,
499e28bee8eSPaolo Bonzini .class_init = slavio_misc_class_init,
500e28bee8eSPaolo Bonzini };
501e28bee8eSPaolo Bonzini
502e28bee8eSPaolo Bonzini static const TypeInfo apc_info = {
503f1a0a79fSAndreas Färber .name = TYPE_APC,
504e28bee8eSPaolo Bonzini .parent = TYPE_SYS_BUS_DEVICE,
505e28bee8eSPaolo Bonzini .instance_size = sizeof(MiscState),
50646eedc0eSxiaoqiang zhao .instance_init = apc_init,
507e28bee8eSPaolo Bonzini };
508e28bee8eSPaolo Bonzini
slavio_misc_register_types(void)509e28bee8eSPaolo Bonzini static void slavio_misc_register_types(void)
510e28bee8eSPaolo Bonzini {
511e28bee8eSPaolo Bonzini type_register_static(&slavio_misc_info);
512e28bee8eSPaolo Bonzini type_register_static(&apc_info);
513e28bee8eSPaolo Bonzini }
514e28bee8eSPaolo Bonzini
515e28bee8eSPaolo Bonzini type_init(slavio_misc_register_types)
516