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