1e68b9b2bSbellard /* 23cbee15bSj_mayer * Heathrow PIC support (OldWorld PowerMac) 3e68b9b2bSbellard * 43cbee15bSj_mayer * Copyright (c) 2005-2007 Fabrice Bellard 53cbee15bSj_mayer * Copyright (c) 2007 Jocelyn Mayer 6e68b9b2bSbellard * 7e68b9b2bSbellard * Permission is hereby granted, free of charge, to any person obtaining a copy 8e68b9b2bSbellard * of this software and associated documentation files (the "Software"), to deal 9e68b9b2bSbellard * in the Software without restriction, including without limitation the rights 10e68b9b2bSbellard * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11e68b9b2bSbellard * copies of the Software, and to permit persons to whom the Software is 12e68b9b2bSbellard * furnished to do so, subject to the following conditions: 13e68b9b2bSbellard * 14e68b9b2bSbellard * The above copyright notice and this permission notice shall be included in 15e68b9b2bSbellard * all copies or substantial portions of the Software. 16e68b9b2bSbellard * 17e68b9b2bSbellard * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18e68b9b2bSbellard * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19e68b9b2bSbellard * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20e68b9b2bSbellard * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21e68b9b2bSbellard * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22e68b9b2bSbellard * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23e68b9b2bSbellard * THE SOFTWARE. 24e68b9b2bSbellard */ 2590191d07SPeter Maydell #include "qemu/osdep.h" 2683c9f4caSPaolo Bonzini #include "hw/hw.h" 2783c9f4caSPaolo Bonzini #include "hw/ppc/mac.h" 28*086df4f3SMark Cave-Ayland #include "hw/intc/heathrow_pic.h" 29e68b9b2bSbellard 30ea026b2fSblueswir1 /* debug PIC */ 31ea026b2fSblueswir1 //#define DEBUG_PIC 32ea026b2fSblueswir1 33ea026b2fSblueswir1 #ifdef DEBUG_PIC 34001faf32SBlue Swirl #define PIC_DPRINTF(fmt, ...) \ 35001faf32SBlue Swirl do { printf("PIC: " fmt , ## __VA_ARGS__); } while (0) 36ea026b2fSblueswir1 #else 37001faf32SBlue Swirl #define PIC_DPRINTF(fmt, ...) 38ea026b2fSblueswir1 #endif 39e68b9b2bSbellard 40*086df4f3SMark Cave-Ayland static inline int heathrow_check_irq(HeathrowPICState *pic) 41e68b9b2bSbellard { 42e68b9b2bSbellard return (pic->events | (pic->levels & pic->level_triggered)) & pic->mask; 43e68b9b2bSbellard } 44e68b9b2bSbellard 45e68b9b2bSbellard /* update the CPU irq state */ 46*086df4f3SMark Cave-Ayland static void heathrow_update_irq(HeathrowState *s) 47e68b9b2bSbellard { 48*086df4f3SMark Cave-Ayland if (heathrow_check_irq(&s->pics[0]) || 49*086df4f3SMark Cave-Ayland heathrow_check_irq(&s->pics[1])) { 503cbee15bSj_mayer qemu_irq_raise(s->irqs[0]); 51e68b9b2bSbellard } else { 523cbee15bSj_mayer qemu_irq_lower(s->irqs[0]); 53e68b9b2bSbellard } 54e68b9b2bSbellard } 55e68b9b2bSbellard 56*086df4f3SMark Cave-Ayland static void heathrow_write(void *opaque, hwaddr addr, 5723c5e4caSAvi Kivity uint64_t value, unsigned size) 58e68b9b2bSbellard { 59*086df4f3SMark Cave-Ayland HeathrowState *s = opaque; 60*086df4f3SMark Cave-Ayland HeathrowPICState *pic; 61e68b9b2bSbellard unsigned int n; 62e68b9b2bSbellard 63e68b9b2bSbellard n = ((addr & 0xfff) - 0x10) >> 4; 64ea026b2fSblueswir1 PIC_DPRINTF("writel: " TARGET_FMT_plx " %u: %08x\n", addr, n, value); 65e68b9b2bSbellard if (n >= 2) 66e68b9b2bSbellard return; 67e68b9b2bSbellard pic = &s->pics[n]; 68e68b9b2bSbellard switch(addr & 0xf) { 69e68b9b2bSbellard case 0x04: 70e68b9b2bSbellard pic->mask = value; 71*086df4f3SMark Cave-Ayland heathrow_update_irq(s); 72e68b9b2bSbellard break; 73e68b9b2bSbellard case 0x08: 74e68b9b2bSbellard /* do not reset level triggered IRQs */ 75e68b9b2bSbellard value &= ~pic->level_triggered; 76e68b9b2bSbellard pic->events &= ~value; 77*086df4f3SMark Cave-Ayland heathrow_update_irq(s); 78e68b9b2bSbellard break; 79e68b9b2bSbellard default: 80e68b9b2bSbellard break; 81e68b9b2bSbellard } 82e68b9b2bSbellard } 83e68b9b2bSbellard 84*086df4f3SMark Cave-Ayland static uint64_t heathrow_read(void *opaque, hwaddr addr, 8523c5e4caSAvi Kivity unsigned size) 86e68b9b2bSbellard { 87*086df4f3SMark Cave-Ayland HeathrowState *s = opaque; 88*086df4f3SMark Cave-Ayland HeathrowPICState *pic; 89e68b9b2bSbellard unsigned int n; 90e68b9b2bSbellard uint32_t value; 91e68b9b2bSbellard 92e68b9b2bSbellard n = ((addr & 0xfff) - 0x10) >> 4; 93e68b9b2bSbellard if (n >= 2) { 94e68b9b2bSbellard value = 0; 95e68b9b2bSbellard } else { 96e68b9b2bSbellard pic = &s->pics[n]; 97e68b9b2bSbellard switch(addr & 0xf) { 98e68b9b2bSbellard case 0x0: 99e68b9b2bSbellard value = pic->events; 100e68b9b2bSbellard break; 101e68b9b2bSbellard case 0x4: 102e68b9b2bSbellard value = pic->mask; 103e68b9b2bSbellard break; 104e68b9b2bSbellard case 0xc: 105e68b9b2bSbellard value = pic->levels; 106e68b9b2bSbellard break; 107e68b9b2bSbellard default: 108e68b9b2bSbellard value = 0; 109e68b9b2bSbellard break; 110e68b9b2bSbellard } 111e68b9b2bSbellard } 112ea026b2fSblueswir1 PIC_DPRINTF("readl: " TARGET_FMT_plx " %u: %08x\n", addr, n, value); 113e68b9b2bSbellard return value; 114e68b9b2bSbellard } 115e68b9b2bSbellard 116*086df4f3SMark Cave-Ayland static const MemoryRegionOps heathrow_ops = { 117*086df4f3SMark Cave-Ayland .read = heathrow_read, 118*086df4f3SMark Cave-Ayland .write = heathrow_write, 1190157644cSAlexander Graf .endianness = DEVICE_LITTLE_ENDIAN, 120e68b9b2bSbellard }; 121e68b9b2bSbellard 122*086df4f3SMark Cave-Ayland static void heathrow_set_irq(void *opaque, int num, int level) 123e68b9b2bSbellard { 124*086df4f3SMark Cave-Ayland HeathrowState *s = opaque; 125*086df4f3SMark Cave-Ayland HeathrowPICState *pic; 126e68b9b2bSbellard unsigned int irq_bit; 127e68b9b2bSbellard 128e68b9b2bSbellard #if defined(DEBUG) 129e68b9b2bSbellard { 130e68b9b2bSbellard static int last_level[64]; 131e68b9b2bSbellard if (last_level[num] != level) { 132ea026b2fSblueswir1 PIC_DPRINTF("set_irq: num=0x%02x level=%d\n", num, level); 133e68b9b2bSbellard last_level[num] = level; 134e68b9b2bSbellard } 135e68b9b2bSbellard } 136e68b9b2bSbellard #endif 137e68b9b2bSbellard pic = &s->pics[1 - (num >> 5)]; 138e68b9b2bSbellard irq_bit = 1 << (num & 0x1f); 139e68b9b2bSbellard if (level) { 140e68b9b2bSbellard pic->events |= irq_bit & ~pic->level_triggered; 141e68b9b2bSbellard pic->levels |= irq_bit; 142e68b9b2bSbellard } else { 143e68b9b2bSbellard pic->levels &= ~irq_bit; 144e68b9b2bSbellard } 145*086df4f3SMark Cave-Ayland heathrow_update_irq(s); 146e68b9b2bSbellard } 147e68b9b2bSbellard 1484acd38ceSJuan Quintela static const VMStateDescription vmstate_heathrow_pic_one = { 1494acd38ceSJuan Quintela .name = "heathrow_pic_one", 1504acd38ceSJuan Quintela .version_id = 0, 1514acd38ceSJuan Quintela .minimum_version_id = 0, 1524acd38ceSJuan Quintela .fields = (VMStateField[]) { 153*086df4f3SMark Cave-Ayland VMSTATE_UINT32(events, HeathrowPICState), 154*086df4f3SMark Cave-Ayland VMSTATE_UINT32(mask, HeathrowPICState), 155*086df4f3SMark Cave-Ayland VMSTATE_UINT32(levels, HeathrowPICState), 156*086df4f3SMark Cave-Ayland VMSTATE_UINT32(level_triggered, HeathrowPICState), 1574acd38ceSJuan Quintela VMSTATE_END_OF_LIST() 1589b64997fSblueswir1 } 1594acd38ceSJuan Quintela }; 1609b64997fSblueswir1 161*086df4f3SMark Cave-Ayland static const VMStateDescription vmstate_heathrow = { 1624acd38ceSJuan Quintela .name = "heathrow_pic", 1634acd38ceSJuan Quintela .version_id = 1, 1644acd38ceSJuan Quintela .minimum_version_id = 1, 1654acd38ceSJuan Quintela .fields = (VMStateField[]) { 166*086df4f3SMark Cave-Ayland VMSTATE_STRUCT_ARRAY(pics, HeathrowState, 2, 1, 167*086df4f3SMark Cave-Ayland vmstate_heathrow_pic_one, HeathrowPICState), 1684acd38ceSJuan Quintela VMSTATE_END_OF_LIST() 1699b64997fSblueswir1 } 1704acd38ceSJuan Quintela }; 1719b64997fSblueswir1 172*086df4f3SMark Cave-Ayland static void heathrow_reset(DeviceState *d) 1736e6b7363Sblueswir1 { 174*086df4f3SMark Cave-Ayland HeathrowState *s = HEATHROW(d); 1756e6b7363Sblueswir1 1766e6b7363Sblueswir1 s->pics[0].level_triggered = 0; 1776e6b7363Sblueswir1 s->pics[1].level_triggered = 0x1ff00000; 1786e6b7363Sblueswir1 } 1796e6b7363Sblueswir1 180*086df4f3SMark Cave-Ayland static void heathrow_init(Object *obj) 181*086df4f3SMark Cave-Ayland { 182*086df4f3SMark Cave-Ayland HeathrowState *s = HEATHROW(obj); 183*086df4f3SMark Cave-Ayland 184*086df4f3SMark Cave-Ayland memory_region_init_io(&s->mem, OBJECT(s), &heathrow_ops, s, 185*086df4f3SMark Cave-Ayland "heathrow-pic", 0x1000); 186*086df4f3SMark Cave-Ayland } 187*086df4f3SMark Cave-Ayland 18823c5e4caSAvi Kivity qemu_irq *heathrow_pic_init(MemoryRegion **pmem, 1893cbee15bSj_mayer int nb_cpus, qemu_irq **irqs) 190e68b9b2bSbellard { 191*086df4f3SMark Cave-Ayland DeviceState *d; 192*086df4f3SMark Cave-Ayland HeathrowState *s; 193e68b9b2bSbellard 194*086df4f3SMark Cave-Ayland d = qdev_create(NULL, TYPE_HEATHROW); 195*086df4f3SMark Cave-Ayland qdev_init_nofail(d); 196*086df4f3SMark Cave-Ayland 197*086df4f3SMark Cave-Ayland s = HEATHROW(d); 1983cbee15bSj_mayer /* only 1 CPU */ 1993cbee15bSj_mayer s->irqs = irqs[0]; 200*086df4f3SMark Cave-Ayland 20123c5e4caSAvi Kivity *pmem = &s->mem; 2023cbee15bSj_mayer 203*086df4f3SMark Cave-Ayland return qemu_allocate_irqs(heathrow_set_irq, s, HEATHROW_NUM_IRQS); 204e68b9b2bSbellard } 205*086df4f3SMark Cave-Ayland 206*086df4f3SMark Cave-Ayland static void heathrow_class_init(ObjectClass *oc, void *data) 207*086df4f3SMark Cave-Ayland { 208*086df4f3SMark Cave-Ayland DeviceClass *dc = DEVICE_CLASS(oc); 209*086df4f3SMark Cave-Ayland 210*086df4f3SMark Cave-Ayland dc->reset = heathrow_reset; 211*086df4f3SMark Cave-Ayland dc->vmsd = &vmstate_heathrow; 212*086df4f3SMark Cave-Ayland set_bit(DEVICE_CATEGORY_MISC, dc->categories); 213*086df4f3SMark Cave-Ayland } 214*086df4f3SMark Cave-Ayland 215*086df4f3SMark Cave-Ayland static const TypeInfo heathrow_type_info = { 216*086df4f3SMark Cave-Ayland .name = TYPE_HEATHROW, 217*086df4f3SMark Cave-Ayland .parent = TYPE_SYS_BUS_DEVICE, 218*086df4f3SMark Cave-Ayland .instance_size = sizeof(HeathrowState), 219*086df4f3SMark Cave-Ayland .instance_init = heathrow_init, 220*086df4f3SMark Cave-Ayland .class_init = heathrow_class_init, 221*086df4f3SMark Cave-Ayland }; 222*086df4f3SMark Cave-Ayland 223*086df4f3SMark Cave-Ayland static void heathrow_register_types(void) 224*086df4f3SMark Cave-Ayland { 225*086df4f3SMark Cave-Ayland type_register_static(&heathrow_type_info); 226*086df4f3SMark Cave-Ayland } 227*086df4f3SMark Cave-Ayland 228*086df4f3SMark Cave-Ayland type_init(heathrow_register_types) 229