17c4166a9SMark Cave-Ayland /* 27c4166a9SMark Cave-Ayland * PowerMac NewWorld MacIO GPIO emulation 37c4166a9SMark Cave-Ayland * 47c4166a9SMark Cave-Ayland * Copyright (c) 2016 Benjamin Herrenschmidt 57c4166a9SMark Cave-Ayland * Copyright (c) 2018 Mark Cave-Ayland 67c4166a9SMark Cave-Ayland * 77c4166a9SMark Cave-Ayland * Permission is hereby granted, free of charge, to any person obtaining a copy 87c4166a9SMark Cave-Ayland * of this software and associated documentation files (the "Software"), to deal 97c4166a9SMark Cave-Ayland * in the Software without restriction, including without limitation the rights 107c4166a9SMark Cave-Ayland * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 117c4166a9SMark Cave-Ayland * copies of the Software, and to permit persons to whom the Software is 127c4166a9SMark Cave-Ayland * furnished to do so, subject to the following conditions: 137c4166a9SMark Cave-Ayland * 147c4166a9SMark Cave-Ayland * The above copyright notice and this permission notice shall be included in 157c4166a9SMark Cave-Ayland * all copies or substantial portions of the Software. 167c4166a9SMark Cave-Ayland * 177c4166a9SMark Cave-Ayland * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 187c4166a9SMark Cave-Ayland * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 197c4166a9SMark Cave-Ayland * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 207c4166a9SMark Cave-Ayland * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 217c4166a9SMark Cave-Ayland * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 227c4166a9SMark Cave-Ayland * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 237c4166a9SMark Cave-Ayland * THE SOFTWARE. 247c4166a9SMark Cave-Ayland */ 257c4166a9SMark Cave-Ayland 267c4166a9SMark Cave-Ayland #include "qemu/osdep.h" 277c4166a9SMark Cave-Ayland #include "hw/hw.h" 287c4166a9SMark Cave-Ayland #include "hw/ppc/mac.h" 29*d6454270SMarkus Armbruster #include "migration/vmstate.h" 307c4166a9SMark Cave-Ayland #include "hw/misc/macio/macio.h" 317c4166a9SMark Cave-Ayland #include "hw/misc/macio/gpio.h" 328f55ac13SMark Cave-Ayland #include "hw/nmi.h" 337c4166a9SMark Cave-Ayland #include "qemu/log.h" 340b8fa32fSMarkus Armbruster #include "qemu/module.h" 357c4166a9SMark Cave-Ayland #include "trace.h" 367c4166a9SMark Cave-Ayland 377c4166a9SMark Cave-Ayland 387c4166a9SMark Cave-Ayland void macio_set_gpio(MacIOGPIOState *s, uint32_t gpio, bool state) 397c4166a9SMark Cave-Ayland { 407c4166a9SMark Cave-Ayland uint8_t new_reg; 417c4166a9SMark Cave-Ayland 427c4166a9SMark Cave-Ayland trace_macio_set_gpio(gpio, state); 437c4166a9SMark Cave-Ayland 447c4166a9SMark Cave-Ayland if (s->gpio_regs[gpio] & 4) { 457c4166a9SMark Cave-Ayland qemu_log_mask(LOG_GUEST_ERROR, 467c4166a9SMark Cave-Ayland "GPIO: Setting GPIO %d while it's an output\n", gpio); 477c4166a9SMark Cave-Ayland } 487c4166a9SMark Cave-Ayland 497c4166a9SMark Cave-Ayland new_reg = s->gpio_regs[gpio] & ~2; 507c4166a9SMark Cave-Ayland if (state) { 517c4166a9SMark Cave-Ayland new_reg |= 2; 527c4166a9SMark Cave-Ayland } 537c4166a9SMark Cave-Ayland 547c4166a9SMark Cave-Ayland if (new_reg == s->gpio_regs[gpio]) { 557c4166a9SMark Cave-Ayland return; 567c4166a9SMark Cave-Ayland } 577c4166a9SMark Cave-Ayland 587c4166a9SMark Cave-Ayland s->gpio_regs[gpio] = new_reg; 597c4166a9SMark Cave-Ayland 607c4166a9SMark Cave-Ayland /* This is will work until we fix the binding between MacIO and 617c4166a9SMark Cave-Ayland * the MPIC properly so we can route all GPIOs and avoid going 627c4166a9SMark Cave-Ayland * via the top level platform code. 637c4166a9SMark Cave-Ayland * 647c4166a9SMark Cave-Ayland * Note that we probably need to get access to the MPIC config to 657c4166a9SMark Cave-Ayland * decode polarity since qemu always use "raise" regardless. 667c4166a9SMark Cave-Ayland * 677c4166a9SMark Cave-Ayland * For now, we hard wire known GPIOs 687c4166a9SMark Cave-Ayland */ 697c4166a9SMark Cave-Ayland 707c4166a9SMark Cave-Ayland switch (gpio) { 717c4166a9SMark Cave-Ayland case 1: 727c4166a9SMark Cave-Ayland /* Level low */ 737c4166a9SMark Cave-Ayland if (!state) { 747c4166a9SMark Cave-Ayland trace_macio_gpio_irq_assert(gpio); 757c4166a9SMark Cave-Ayland qemu_irq_raise(s->gpio_extirqs[gpio]); 767c4166a9SMark Cave-Ayland } else { 777c4166a9SMark Cave-Ayland trace_macio_gpio_irq_deassert(gpio); 787c4166a9SMark Cave-Ayland qemu_irq_lower(s->gpio_extirqs[gpio]); 797c4166a9SMark Cave-Ayland } 807c4166a9SMark Cave-Ayland break; 817c4166a9SMark Cave-Ayland 827c4166a9SMark Cave-Ayland case 9: 837c4166a9SMark Cave-Ayland /* Edge, triggered by NMI below */ 847c4166a9SMark Cave-Ayland if (state) { 857c4166a9SMark Cave-Ayland trace_macio_gpio_irq_assert(gpio); 867c4166a9SMark Cave-Ayland qemu_irq_raise(s->gpio_extirqs[gpio]); 877c4166a9SMark Cave-Ayland } else { 887c4166a9SMark Cave-Ayland trace_macio_gpio_irq_deassert(gpio); 897c4166a9SMark Cave-Ayland qemu_irq_lower(s->gpio_extirqs[gpio]); 907c4166a9SMark Cave-Ayland } 917c4166a9SMark Cave-Ayland break; 927c4166a9SMark Cave-Ayland 937c4166a9SMark Cave-Ayland default: 947c4166a9SMark Cave-Ayland qemu_log_mask(LOG_UNIMP, "GPIO: setting unimplemented GPIO %d", gpio); 957c4166a9SMark Cave-Ayland } 967c4166a9SMark Cave-Ayland } 977c4166a9SMark Cave-Ayland 987c4166a9SMark Cave-Ayland static void macio_gpio_write(void *opaque, hwaddr addr, uint64_t value, 997c4166a9SMark Cave-Ayland unsigned size) 1007c4166a9SMark Cave-Ayland { 1017c4166a9SMark Cave-Ayland MacIOGPIOState *s = opaque; 1027c4166a9SMark Cave-Ayland uint8_t ibit; 1037c4166a9SMark Cave-Ayland 1047c4166a9SMark Cave-Ayland trace_macio_gpio_write(addr, value); 1057c4166a9SMark Cave-Ayland 1067c4166a9SMark Cave-Ayland /* Levels regs are read-only */ 1077c4166a9SMark Cave-Ayland if (addr < 8) { 1087c4166a9SMark Cave-Ayland return; 1097c4166a9SMark Cave-Ayland } 1107c4166a9SMark Cave-Ayland 1117c4166a9SMark Cave-Ayland addr -= 8; 1127c4166a9SMark Cave-Ayland if (addr < 36) { 1137c4166a9SMark Cave-Ayland value &= ~2; 1147c4166a9SMark Cave-Ayland 1157c4166a9SMark Cave-Ayland if (value & 4) { 1167c4166a9SMark Cave-Ayland ibit = (value & 1) << 1; 1177c4166a9SMark Cave-Ayland } else { 1187c4166a9SMark Cave-Ayland ibit = s->gpio_regs[addr] & 2; 1197c4166a9SMark Cave-Ayland } 1207c4166a9SMark Cave-Ayland 1217c4166a9SMark Cave-Ayland s->gpio_regs[addr] = value | ibit; 1227c4166a9SMark Cave-Ayland } 1237c4166a9SMark Cave-Ayland } 1247c4166a9SMark Cave-Ayland 1257c4166a9SMark Cave-Ayland static uint64_t macio_gpio_read(void *opaque, hwaddr addr, unsigned size) 1267c4166a9SMark Cave-Ayland { 1277c4166a9SMark Cave-Ayland MacIOGPIOState *s = opaque; 1287c4166a9SMark Cave-Ayland uint64_t val = 0; 1297c4166a9SMark Cave-Ayland 1307c4166a9SMark Cave-Ayland /* Levels regs */ 1317c4166a9SMark Cave-Ayland if (addr < 8) { 1327c4166a9SMark Cave-Ayland val = s->gpio_levels[addr]; 1337c4166a9SMark Cave-Ayland } else { 1347c4166a9SMark Cave-Ayland addr -= 8; 1357c4166a9SMark Cave-Ayland 1367c4166a9SMark Cave-Ayland if (addr < 36) { 1377c4166a9SMark Cave-Ayland val = s->gpio_regs[addr]; 1387c4166a9SMark Cave-Ayland } 1397c4166a9SMark Cave-Ayland } 1407c4166a9SMark Cave-Ayland 1417c4166a9SMark Cave-Ayland trace_macio_gpio_write(addr, val); 1427c4166a9SMark Cave-Ayland return val; 1437c4166a9SMark Cave-Ayland } 1447c4166a9SMark Cave-Ayland 1457c4166a9SMark Cave-Ayland static const MemoryRegionOps macio_gpio_ops = { 1467c4166a9SMark Cave-Ayland .read = macio_gpio_read, 1477c4166a9SMark Cave-Ayland .write = macio_gpio_write, 1487c4166a9SMark Cave-Ayland .endianness = DEVICE_LITTLE_ENDIAN, 1497c4166a9SMark Cave-Ayland .impl = { 1507c4166a9SMark Cave-Ayland .min_access_size = 1, 1517c4166a9SMark Cave-Ayland .max_access_size = 1, 1527c4166a9SMark Cave-Ayland }, 1537c4166a9SMark Cave-Ayland }; 1547c4166a9SMark Cave-Ayland 1557c4166a9SMark Cave-Ayland static void macio_gpio_realize(DeviceState *dev, Error **errp) 1567c4166a9SMark Cave-Ayland { 1577c4166a9SMark Cave-Ayland MacIOGPIOState *s = MACIO_GPIO(dev); 1587c4166a9SMark Cave-Ayland 1597c4166a9SMark Cave-Ayland s->gpio_extirqs[1] = qdev_get_gpio_in(DEVICE(s->pic), 1607c4166a9SMark Cave-Ayland NEWWORLD_EXTING_GPIO1); 1617c4166a9SMark Cave-Ayland s->gpio_extirqs[9] = qdev_get_gpio_in(DEVICE(s->pic), 1627c4166a9SMark Cave-Ayland NEWWORLD_EXTING_GPIO9); 1637c4166a9SMark Cave-Ayland } 1647c4166a9SMark Cave-Ayland 1657c4166a9SMark Cave-Ayland static void macio_gpio_init(Object *obj) 1667c4166a9SMark Cave-Ayland { 1677c4166a9SMark Cave-Ayland SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 1687c4166a9SMark Cave-Ayland MacIOGPIOState *s = MACIO_GPIO(obj); 1697c4166a9SMark Cave-Ayland 1707c4166a9SMark Cave-Ayland object_property_add_link(obj, "pic", TYPE_OPENPIC, 1717c4166a9SMark Cave-Ayland (Object **) &s->pic, 1727c4166a9SMark Cave-Ayland qdev_prop_allow_set_link_before_realize, 1737c4166a9SMark Cave-Ayland 0, NULL); 1747c4166a9SMark Cave-Ayland 1757c4166a9SMark Cave-Ayland memory_region_init_io(&s->gpiomem, OBJECT(s), &macio_gpio_ops, obj, 1767c4166a9SMark Cave-Ayland "gpio", 0x30); 1777c4166a9SMark Cave-Ayland sysbus_init_mmio(sbd, &s->gpiomem); 1787c4166a9SMark Cave-Ayland } 1797c4166a9SMark Cave-Ayland 1807c4166a9SMark Cave-Ayland static const VMStateDescription vmstate_macio_gpio = { 1817c4166a9SMark Cave-Ayland .name = "macio_gpio", 1827c4166a9SMark Cave-Ayland .version_id = 0, 1837c4166a9SMark Cave-Ayland .minimum_version_id = 0, 1847c4166a9SMark Cave-Ayland .fields = (VMStateField[]) { 1857c4166a9SMark Cave-Ayland VMSTATE_UINT8_ARRAY(gpio_levels, MacIOGPIOState, 8), 1867c4166a9SMark Cave-Ayland VMSTATE_UINT8_ARRAY(gpio_regs, MacIOGPIOState, 36), 1877c4166a9SMark Cave-Ayland VMSTATE_END_OF_LIST() 1887c4166a9SMark Cave-Ayland } 1897c4166a9SMark Cave-Ayland }; 1907c4166a9SMark Cave-Ayland 1917c4166a9SMark Cave-Ayland static void macio_gpio_reset(DeviceState *dev) 1927c4166a9SMark Cave-Ayland { 1937c4166a9SMark Cave-Ayland MacIOGPIOState *s = MACIO_GPIO(dev); 1947c4166a9SMark Cave-Ayland 1957c4166a9SMark Cave-Ayland /* GPIO 1 is up by default */ 1967c4166a9SMark Cave-Ayland macio_set_gpio(s, 1, true); 1977c4166a9SMark Cave-Ayland } 1987c4166a9SMark Cave-Ayland 1998f55ac13SMark Cave-Ayland static void macio_gpio_nmi(NMIState *n, int cpu_index, Error **errp) 2008f55ac13SMark Cave-Ayland { 2018f55ac13SMark Cave-Ayland macio_set_gpio(MACIO_GPIO(n), 9, true); 2028f55ac13SMark Cave-Ayland macio_set_gpio(MACIO_GPIO(n), 9, false); 2038f55ac13SMark Cave-Ayland } 2048f55ac13SMark Cave-Ayland 2057c4166a9SMark Cave-Ayland static void macio_gpio_class_init(ObjectClass *oc, void *data) 2067c4166a9SMark Cave-Ayland { 2077c4166a9SMark Cave-Ayland DeviceClass *dc = DEVICE_CLASS(oc); 2088f55ac13SMark Cave-Ayland NMIClass *nc = NMI_CLASS(oc); 2097c4166a9SMark Cave-Ayland 2107c4166a9SMark Cave-Ayland dc->realize = macio_gpio_realize; 2117c4166a9SMark Cave-Ayland dc->reset = macio_gpio_reset; 2127c4166a9SMark Cave-Ayland dc->vmsd = &vmstate_macio_gpio; 2138f55ac13SMark Cave-Ayland nc->nmi_monitor_handler = macio_gpio_nmi; 2147c4166a9SMark Cave-Ayland } 2157c4166a9SMark Cave-Ayland 2167c4166a9SMark Cave-Ayland static const TypeInfo macio_gpio_init_info = { 2177c4166a9SMark Cave-Ayland .name = TYPE_MACIO_GPIO, 2187c4166a9SMark Cave-Ayland .parent = TYPE_SYS_BUS_DEVICE, 2197c4166a9SMark Cave-Ayland .instance_size = sizeof(MacIOGPIOState), 2207c4166a9SMark Cave-Ayland .instance_init = macio_gpio_init, 2217c4166a9SMark Cave-Ayland .class_init = macio_gpio_class_init, 2228f55ac13SMark Cave-Ayland .interfaces = (InterfaceInfo[]) { 2238f55ac13SMark Cave-Ayland { TYPE_NMI }, 2248f55ac13SMark Cave-Ayland { } 2258f55ac13SMark Cave-Ayland }, 2267c4166a9SMark Cave-Ayland }; 2277c4166a9SMark Cave-Ayland 2287c4166a9SMark Cave-Ayland static void macio_gpio_register_types(void) 2297c4166a9SMark Cave-Ayland { 2307c4166a9SMark Cave-Ayland type_register_static(&macio_gpio_init_info); 2317c4166a9SMark Cave-Ayland } 2327c4166a9SMark Cave-Ayland 2337c4166a9SMark Cave-Ayland type_init(macio_gpio_register_types) 234