1 /* 2 * PowerMac NewWorld MacIO GPIO emulation 3 * 4 * Copyright (c) 2016 Benjamin Herrenschmidt 5 * Copyright (c) 2018 Mark Cave-Ayland 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 26 #include "qemu/osdep.h" 27 #include "hw/qdev-properties.h" 28 #include "migration/vmstate.h" 29 #include "hw/misc/macio/macio.h" 30 #include "hw/misc/macio/gpio.h" 31 #include "hw/irq.h" 32 #include "hw/nmi.h" 33 #include "qemu/log.h" 34 #include "qemu/module.h" 35 #include "trace.h" 36 37 enum MacioGPIORegisterBits { 38 OUT_DATA = 1, 39 IN_DATA = 2, 40 OUT_ENABLE = 4, 41 }; 42 43 void macio_set_gpio(MacIOGPIOState *s, uint32_t gpio, bool state) 44 { 45 uint8_t new_reg; 46 47 trace_macio_set_gpio(gpio, state); 48 49 if (s->gpio_regs[gpio] & OUT_ENABLE) { 50 qemu_log_mask(LOG_GUEST_ERROR, 51 "GPIO: Setting GPIO %d while it's an output\n", gpio); 52 } 53 54 new_reg = s->gpio_regs[gpio] & ~IN_DATA; 55 if (state) { 56 new_reg |= IN_DATA; 57 } 58 59 if (new_reg == s->gpio_regs[gpio]) { 60 return; 61 } 62 63 s->gpio_regs[gpio] = new_reg; 64 65 /* 66 * Note that we probably need to get access to the MPIC config to 67 * decode polarity since qemu always use "raise" regardless. 68 * 69 * For now, we hard wire known GPIOs 70 */ 71 72 switch (gpio) { 73 case 1: 74 /* Level low */ 75 if (!state) { 76 trace_macio_gpio_irq_assert(gpio); 77 qemu_irq_raise(s->gpio_extirqs[gpio]); 78 } else { 79 trace_macio_gpio_irq_deassert(gpio); 80 qemu_irq_lower(s->gpio_extirqs[gpio]); 81 } 82 break; 83 84 case 9: 85 /* Edge, triggered by NMI below */ 86 if (state) { 87 trace_macio_gpio_irq_assert(gpio); 88 qemu_irq_raise(s->gpio_extirqs[gpio]); 89 } else { 90 trace_macio_gpio_irq_deassert(gpio); 91 qemu_irq_lower(s->gpio_extirqs[gpio]); 92 } 93 break; 94 95 default: 96 qemu_log_mask(LOG_UNIMP, "GPIO: setting unimplemented GPIO %d", gpio); 97 } 98 } 99 100 static void macio_gpio_write(void *opaque, hwaddr addr, uint64_t value, 101 unsigned size) 102 { 103 MacIOGPIOState *s = opaque; 104 uint8_t ibit; 105 106 trace_macio_gpio_write(addr, value); 107 108 /* Levels regs are read-only */ 109 if (addr < 8) { 110 return; 111 } 112 113 addr -= 8; 114 if (addr < 36) { 115 value &= ~IN_DATA; 116 117 if (value & OUT_ENABLE) { 118 ibit = (value & OUT_DATA) << 1; 119 } else { 120 ibit = s->gpio_regs[addr] & IN_DATA; 121 } 122 123 s->gpio_regs[addr] = value | ibit; 124 } 125 } 126 127 static uint64_t macio_gpio_read(void *opaque, hwaddr addr, unsigned size) 128 { 129 MacIOGPIOState *s = opaque; 130 uint64_t val = 0; 131 132 /* Levels regs */ 133 if (addr < 8) { 134 val = s->gpio_levels[addr]; 135 } else { 136 addr -= 8; 137 138 if (addr < 36) { 139 val = s->gpio_regs[addr]; 140 } 141 } 142 143 trace_macio_gpio_read(addr, val); 144 return val; 145 } 146 147 static const MemoryRegionOps macio_gpio_ops = { 148 .read = macio_gpio_read, 149 .write = macio_gpio_write, 150 .endianness = DEVICE_LITTLE_ENDIAN, 151 .impl = { 152 .min_access_size = 1, 153 .max_access_size = 1, 154 }, 155 }; 156 157 static void macio_gpio_init(Object *obj) 158 { 159 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 160 MacIOGPIOState *s = MACIO_GPIO(obj); 161 int i; 162 163 for (i = 0; i < 10; i++) { 164 sysbus_init_irq(sbd, &s->gpio_extirqs[i]); 165 } 166 167 memory_region_init_io(&s->gpiomem, OBJECT(s), &macio_gpio_ops, obj, 168 "gpio", 0x30); 169 sysbus_init_mmio(sbd, &s->gpiomem); 170 } 171 172 static const VMStateDescription vmstate_macio_gpio = { 173 .name = "macio_gpio", 174 .version_id = 0, 175 .minimum_version_id = 0, 176 .fields = (const VMStateField[]) { 177 VMSTATE_UINT8_ARRAY(gpio_levels, MacIOGPIOState, 8), 178 VMSTATE_UINT8_ARRAY(gpio_regs, MacIOGPIOState, 36), 179 VMSTATE_END_OF_LIST() 180 } 181 }; 182 183 static void macio_gpio_reset(DeviceState *dev) 184 { 185 MacIOGPIOState *s = MACIO_GPIO(dev); 186 187 /* GPIO 1 is up by default */ 188 macio_set_gpio(s, 1, true); 189 } 190 191 static void macio_gpio_nmi(NMIState *n, int cpu_index, Error **errp) 192 { 193 macio_set_gpio(MACIO_GPIO(n), 9, true); 194 macio_set_gpio(MACIO_GPIO(n), 9, false); 195 } 196 197 static void macio_gpio_class_init(ObjectClass *oc, const void *data) 198 { 199 DeviceClass *dc = DEVICE_CLASS(oc); 200 NMIClass *nc = NMI_CLASS(oc); 201 202 device_class_set_legacy_reset(dc, macio_gpio_reset); 203 dc->vmsd = &vmstate_macio_gpio; 204 nc->nmi_monitor_handler = macio_gpio_nmi; 205 } 206 207 static const TypeInfo macio_gpio_init_info = { 208 .name = TYPE_MACIO_GPIO, 209 .parent = TYPE_SYS_BUS_DEVICE, 210 .instance_size = sizeof(MacIOGPIOState), 211 .instance_init = macio_gpio_init, 212 .class_init = macio_gpio_class_init, 213 .interfaces = (const InterfaceInfo[]) { 214 { TYPE_NMI }, 215 { } 216 }, 217 }; 218 219 static void macio_gpio_register_types(void) 220 { 221 type_register_static(&macio_gpio_init_info); 222 } 223 224 type_init(macio_gpio_register_types) 225