1c68c4a56SPaolo Bonzini /*
2c68c4a56SPaolo Bonzini * QEMU PowerPC MPC8544 global util pseudo-device
3c68c4a56SPaolo Bonzini *
4c68c4a56SPaolo Bonzini * Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved.
5c68c4a56SPaolo Bonzini *
6c68c4a56SPaolo Bonzini * Author: Alexander Graf, <alex@csgraf.de>
7c68c4a56SPaolo Bonzini *
8c68c4a56SPaolo Bonzini * This is free software; you can redistribute it and/or modify
9c68c4a56SPaolo Bonzini * it under the terms of the GNU General Public License as published by
10c68c4a56SPaolo Bonzini * the Free Software Foundation; either version 2 of the License, or
11c68c4a56SPaolo Bonzini * (at your option) any later version.
12c68c4a56SPaolo Bonzini *
13c68c4a56SPaolo Bonzini * *****************************************************************
14c68c4a56SPaolo Bonzini *
15c68c4a56SPaolo Bonzini * The documentation for this device is noted in the MPC8544 documentation,
16c68c4a56SPaolo Bonzini * file name "MPC8544ERM.pdf". You can easily find it on the web.
17c68c4a56SPaolo Bonzini *
18c68c4a56SPaolo Bonzini */
19c68c4a56SPaolo Bonzini
200d75590dSPeter Maydell #include "qemu/osdep.h"
21b3b5c5d3SCédric Le Goater #include "qemu/log.h"
2254d31236SMarkus Armbruster #include "sysemu/runstate.h"
234771d756SPaolo Bonzini #include "cpu.h"
24c68c4a56SPaolo Bonzini #include "hw/sysbus.h"
25db1015e9SEduardo Habkost #include "qom/object.h"
26c68c4a56SPaolo Bonzini
27c68c4a56SPaolo Bonzini #define MPC8544_GUTS_MMIO_SIZE 0x1000
28c68c4a56SPaolo Bonzini #define MPC8544_GUTS_RSTCR_RESET 0x02
29c68c4a56SPaolo Bonzini
30c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_PORPLLSR 0x00
316b0cc658SBernhard Beschow REG32(GUTS_PORPLLSR, 0x00)
326b0cc658SBernhard Beschow FIELD(GUTS_PORPLLSR, E500_1_RATIO, 24, 6)
336b0cc658SBernhard Beschow FIELD(GUTS_PORPLLSR, E500_0_RATIO, 16, 6)
346b0cc658SBernhard Beschow FIELD(GUTS_PORPLLSR, DDR_RATIO, 9, 5)
356b0cc658SBernhard Beschow FIELD(GUTS_PORPLLSR, PLAT_RATIO, 1, 5)
366b0cc658SBernhard Beschow
37c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_PORBMSR 0x04
38c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_PORIMPSCR 0x08
39c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_PORDEVSR 0x0C
40c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_PORDBGMSR 0x10
41c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_PORDEVSR2 0x14
42c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_GPPORCR 0x20
43c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_GPIOCR 0x30
44c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_GPOUTDR 0x40
45c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_GPINDR 0x50
46c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_PMUXCR 0x60
47c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_DEVDISR 0x70
48c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_POWMGTCSR 0x80
49c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_MCPSUMR 0x90
50c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_RSTRSCR 0x94
51c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_PVR 0xA0
52c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_SVR 0xA4
53c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_RSTCR 0xB0
54c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_IOVSELSR 0xC0
55c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_DDRCSR 0xB20
56c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_DDRCDR 0xB24
57c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_DDRCLKDR 0xB28
58c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_CLKOCR 0xE00
59c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_SRDS1CR1 0xF04
60c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_SRDS2CR1 0xF10
61c68c4a56SPaolo Bonzini #define MPC8544_GUTS_ADDR_SRDS2CR3 0xF18
62c68c4a56SPaolo Bonzini
6343f691e9SAndreas Färber #define TYPE_MPC8544_GUTS "mpc8544-guts"
648063396bSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(GutsState, MPC8544_GUTS)
6543f691e9SAndreas Färber
66c68c4a56SPaolo Bonzini struct GutsState {
6743f691e9SAndreas Färber /*< private >*/
6843f691e9SAndreas Färber SysBusDevice parent_obj;
6943f691e9SAndreas Färber /*< public >*/
7043f691e9SAndreas Färber
71c68c4a56SPaolo Bonzini MemoryRegion iomem;
72c68c4a56SPaolo Bonzini };
73c68c4a56SPaolo Bonzini
74c68c4a56SPaolo Bonzini
mpc8544_guts_read(void * opaque,hwaddr addr,unsigned size)75c68c4a56SPaolo Bonzini static uint64_t mpc8544_guts_read(void *opaque, hwaddr addr,
76c68c4a56SPaolo Bonzini unsigned size)
77c68c4a56SPaolo Bonzini {
78c68c4a56SPaolo Bonzini uint32_t value = 0;
79794511bcSPhilippe Mathieu-Daudé CPUPPCState *env = cpu_env(current_cpu);
80c68c4a56SPaolo Bonzini
81c68c4a56SPaolo Bonzini addr &= MPC8544_GUTS_MMIO_SIZE - 1;
82c68c4a56SPaolo Bonzini switch (addr) {
836b0cc658SBernhard Beschow case MPC8544_GUTS_ADDR_PORPLLSR:
846b0cc658SBernhard Beschow value = FIELD_DP32(value, GUTS_PORPLLSR, E500_1_RATIO, 6); /* 3:1 */
856b0cc658SBernhard Beschow value = FIELD_DP32(value, GUTS_PORPLLSR, E500_0_RATIO, 6); /* 3:1 */
866b0cc658SBernhard Beschow value = FIELD_DP32(value, GUTS_PORPLLSR, DDR_RATIO, 12); /* 12:1 */
876b0cc658SBernhard Beschow value = FIELD_DP32(value, GUTS_PORPLLSR, PLAT_RATIO, 6); /* 6:1 */
886b0cc658SBernhard Beschow break;
89c68c4a56SPaolo Bonzini case MPC8544_GUTS_ADDR_PVR:
90c68c4a56SPaolo Bonzini value = env->spr[SPR_PVR];
91c68c4a56SPaolo Bonzini break;
92c68c4a56SPaolo Bonzini case MPC8544_GUTS_ADDR_SVR:
93c68c4a56SPaolo Bonzini value = env->spr[SPR_E500_SVR];
94c68c4a56SPaolo Bonzini break;
95c68c4a56SPaolo Bonzini default:
96b3b5c5d3SCédric Le Goater qemu_log_mask(LOG_GUEST_ERROR,
97b3b5c5d3SCédric Le Goater "%s: Unknown register 0x%" HWADDR_PRIx "\n",
98b3b5c5d3SCédric Le Goater __func__, addr);
99c68c4a56SPaolo Bonzini break;
100c68c4a56SPaolo Bonzini }
101c68c4a56SPaolo Bonzini
102c68c4a56SPaolo Bonzini return value;
103c68c4a56SPaolo Bonzini }
104c68c4a56SPaolo Bonzini
mpc8544_guts_write(void * opaque,hwaddr addr,uint64_t value,unsigned size)105c68c4a56SPaolo Bonzini static void mpc8544_guts_write(void *opaque, hwaddr addr,
106c68c4a56SPaolo Bonzini uint64_t value, unsigned size)
107c68c4a56SPaolo Bonzini {
108c68c4a56SPaolo Bonzini addr &= MPC8544_GUTS_MMIO_SIZE - 1;
109c68c4a56SPaolo Bonzini
110c68c4a56SPaolo Bonzini switch (addr) {
111c68c4a56SPaolo Bonzini case MPC8544_GUTS_ADDR_RSTCR:
112c68c4a56SPaolo Bonzini if (value & MPC8544_GUTS_RSTCR_RESET) {
113cf83f140SEric Blake qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
114c68c4a56SPaolo Bonzini }
115c68c4a56SPaolo Bonzini break;
116c68c4a56SPaolo Bonzini default:
117b3b5c5d3SCédric Le Goater qemu_log_mask(LOG_GUEST_ERROR, "%s: Unknown register 0x%" HWADDR_PRIx
118b3b5c5d3SCédric Le Goater " = 0x%" PRIx64 "\n", __func__, addr, value);
119c68c4a56SPaolo Bonzini break;
120c68c4a56SPaolo Bonzini }
121c68c4a56SPaolo Bonzini }
122c68c4a56SPaolo Bonzini
123c68c4a56SPaolo Bonzini static const MemoryRegionOps mpc8544_guts_ops = {
124c68c4a56SPaolo Bonzini .read = mpc8544_guts_read,
125c68c4a56SPaolo Bonzini .write = mpc8544_guts_write,
126c68c4a56SPaolo Bonzini .endianness = DEVICE_BIG_ENDIAN,
127c68c4a56SPaolo Bonzini .valid = {
128c68c4a56SPaolo Bonzini .min_access_size = 4,
129c68c4a56SPaolo Bonzini .max_access_size = 4,
130c68c4a56SPaolo Bonzini },
131c68c4a56SPaolo Bonzini };
132c68c4a56SPaolo Bonzini
mpc8544_guts_initfn(Object * obj)1337587ea5bSAndreas Färber static void mpc8544_guts_initfn(Object *obj)
134c68c4a56SPaolo Bonzini {
1357587ea5bSAndreas Färber SysBusDevice *d = SYS_BUS_DEVICE(obj);
1367587ea5bSAndreas Färber GutsState *s = MPC8544_GUTS(obj);
137c68c4a56SPaolo Bonzini
13840c5dce9SPaolo Bonzini memory_region_init_io(&s->iomem, OBJECT(s), &mpc8544_guts_ops, s,
1391f1a83f4SAndreas Färber "mpc8544.guts", MPC8544_GUTS_MMIO_SIZE);
1407587ea5bSAndreas Färber sysbus_init_mmio(d, &s->iomem);
141c68c4a56SPaolo Bonzini }
142c68c4a56SPaolo Bonzini
143*0ab117f0SBernhard Beschow static const TypeInfo mpc8544_guts_types[] = {
144*0ab117f0SBernhard Beschow {
14543f691e9SAndreas Färber .name = TYPE_MPC8544_GUTS,
146c68c4a56SPaolo Bonzini .parent = TYPE_SYS_BUS_DEVICE,
147c68c4a56SPaolo Bonzini .instance_size = sizeof(GutsState),
1487587ea5bSAndreas Färber .instance_init = mpc8544_guts_initfn,
149*0ab117f0SBernhard Beschow },
150c68c4a56SPaolo Bonzini };
151c68c4a56SPaolo Bonzini
152*0ab117f0SBernhard Beschow DEFINE_TYPES(mpc8544_guts_types)
153