diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-02-05 16:12:12 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-04-08 18:13:16 +0200 |
commit | 7702e47c21e9e7c9962a25de03caa999ea4cd2ea (patch) | |
tree | 743d21340fcd4e45df99c61c875bfbf9a3eb56cb /hw/exynos4210_combiner.c | |
parent | d2c0bd845847820e4abd99638aa2e9b90611a5bf (diff) |
hw: move interrupt controllers to hw/intc/, configure with default-configs/
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/exynos4210_combiner.c')
-rw-r--r-- | hw/exynos4210_combiner.c | 455 |
1 files changed, 0 insertions, 455 deletions
diff --git a/hw/exynos4210_combiner.c b/hw/exynos4210_combiner.c deleted file mode 100644 index 6874287302..0000000000 --- a/hw/exynos4210_combiner.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Samsung exynos4210 Interrupt Combiner - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. - * All rights reserved. - * - * Evgeny Voevodin <e.voevodin@samsung.com> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, see <http://www.gnu.org/licenses/>. - */ - -/* - * Exynos4210 Combiner represents an OR gate for SOC's IRQ lines. It combines - * IRQ sources into groups and provides signal output to GIC from each group. It - * is driven by common mask and enable/disable logic. Take a note that not all - * IRQs are passed to GIC through Combiner. - */ - -#include "hw/sysbus.h" - -#include "hw/arm/exynos4210.h" - -//#define DEBUG_COMBINER - -#ifdef DEBUG_COMBINER -#define DPRINTF(fmt, ...) \ - do { fprintf(stdout, "COMBINER: [%s:%d] " fmt, __func__ , __LINE__, \ - ## __VA_ARGS__); } while (0) -#else -#define DPRINTF(fmt, ...) do {} while (0) -#endif - -#define IIC_NGRP 64 /* Internal Interrupt Combiner - Groups number */ -#define IIC_NIRQ (IIC_NGRP * 8)/* Internal Interrupt Combiner - Interrupts number */ -#define IIC_REGION_SIZE 0x108 /* Size of memory mapped region */ -#define IIC_REGSET_SIZE 0x41 - -/* - * State for each output signal of internal combiner - */ -typedef struct CombinerGroupState { - uint8_t src_mask; /* 1 - source enabled, 0 - disabled */ - uint8_t src_pending; /* Pending source interrupts before masking */ -} CombinerGroupState; - -typedef struct Exynos4210CombinerState { - SysBusDevice busdev; - MemoryRegion iomem; - - struct CombinerGroupState group[IIC_NGRP]; - uint32_t reg_set[IIC_REGSET_SIZE]; - uint32_t icipsr[2]; - uint32_t external; /* 1 means that this combiner is external */ - - qemu_irq output_irq[IIC_NGRP]; -} Exynos4210CombinerState; - -static const VMStateDescription vmstate_exynos4210_combiner_group_state = { - .name = "exynos4210.combiner.groupstate", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { - VMSTATE_UINT8(src_mask, CombinerGroupState), - VMSTATE_UINT8(src_pending, CombinerGroupState), - VMSTATE_END_OF_LIST() - } -}; - -static const VMStateDescription vmstate_exynos4210_combiner = { - .name = "exynos4210.combiner", - .version_id = 1, - .minimum_version_id = 1, - .minimum_version_id_old = 1, - .fields = (VMStateField[]) { - VMSTATE_STRUCT_ARRAY(group, Exynos4210CombinerState, IIC_NGRP, 0, - vmstate_exynos4210_combiner_group_state, CombinerGroupState), - VMSTATE_UINT32_ARRAY(reg_set, Exynos4210CombinerState, - IIC_REGSET_SIZE), - VMSTATE_UINT32_ARRAY(icipsr, Exynos4210CombinerState, 2), - VMSTATE_UINT32(external, Exynos4210CombinerState), - VMSTATE_END_OF_LIST() - } -}; - -/* - * Get Combiner input GPIO into irqs structure - */ -void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev, - int ext) -{ - int n; - int bit; - int max; - qemu_irq *irq; - - max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ : - EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; - irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq; - - /* - * Some IRQs of Int/External Combiner are going to two Combiners groups, - * so let split them. - */ - for (n = 0; n < max; n++) { - - bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n); - - switch (n) { - /* MDNIE_LCD1 INTG1 */ - case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ... - EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3): - irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n), - irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]); - continue; - - /* TMU INTG3 */ - case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4): - irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n), - irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]); - continue; - - /* LCD1 INTG12 */ - case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ... - EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3): - irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n), - irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]); - continue; - - /* Multi-Core Timer INTG12 */ - case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ... - EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8): - irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n), - irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]); - continue; - - /* Multi-Core Timer INTG35 */ - case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ... - EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8): - irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n), - irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]); - continue; - - /* Multi-Core Timer INTG51 */ - case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ... - EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8): - irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n), - irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]); - continue; - - /* Multi-Core Timer INTG53 */ - case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ... - EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8): - irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n), - irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]); - continue; - } - - irq[n] = qdev_get_gpio_in(dev, n); - } -} - -static uint64_t -exynos4210_combiner_read(void *opaque, hwaddr offset, unsigned size) -{ - struct Exynos4210CombinerState *s = - (struct Exynos4210CombinerState *)opaque; - uint32_t req_quad_base_n; /* Base of registers quad. Multiply it by 4 and - get a start of corresponding group quad */ - uint32_t grp_quad_base_n; /* Base of group quad */ - uint32_t reg_n; /* Register number inside the quad */ - uint32_t val; - - req_quad_base_n = offset >> 4; - grp_quad_base_n = req_quad_base_n << 2; - reg_n = (offset - (req_quad_base_n << 4)) >> 2; - - if (req_quad_base_n >= IIC_NGRP) { - /* Read of ICIPSR register */ - return s->icipsr[reg_n]; - } - - val = 0; - - switch (reg_n) { - /* IISTR */ - case 2: - val |= s->group[grp_quad_base_n].src_pending; - val |= s->group[grp_quad_base_n + 1].src_pending << 8; - val |= s->group[grp_quad_base_n + 2].src_pending << 16; - val |= s->group[grp_quad_base_n + 3].src_pending << 24; - break; - /* IIMSR */ - case 3: - val |= s->group[grp_quad_base_n].src_mask & - s->group[grp_quad_base_n].src_pending; - val |= (s->group[grp_quad_base_n + 1].src_mask & - s->group[grp_quad_base_n + 1].src_pending) << 8; - val |= (s->group[grp_quad_base_n + 2].src_mask & - s->group[grp_quad_base_n + 2].src_pending) << 16; - val |= (s->group[grp_quad_base_n + 3].src_mask & - s->group[grp_quad_base_n + 3].src_pending) << 24; - break; - default: - if (offset >> 2 >= IIC_REGSET_SIZE) { - hw_error("exynos4210.combiner: overflow of reg_set by 0x" - TARGET_FMT_plx "offset\n", offset); - } - val = s->reg_set[offset >> 2]; - return 0; - } - return val; -} - -static void exynos4210_combiner_update(void *opaque, uint8_t group_n) -{ - struct Exynos4210CombinerState *s = - (struct Exynos4210CombinerState *)opaque; - - /* Send interrupt if needed */ - if (s->group[group_n].src_mask & s->group[group_n].src_pending) { -#ifdef DEBUG_COMBINER - if (group_n != 26) { - /* skip uart */ - DPRINTF("%s raise IRQ[%d]\n", s->external ? "EXT" : "INT", group_n); - } -#endif - - /* Set Combiner interrupt pending status after masking */ - if (group_n >= 32) { - s->icipsr[1] |= 1 << (group_n - 32); - } else { - s->icipsr[0] |= 1 << group_n; - } - - qemu_irq_raise(s->output_irq[group_n]); - } else { -#ifdef DEBUG_COMBINER - if (group_n != 26) { - /* skip uart */ - DPRINTF("%s lower IRQ[%d]\n", s->external ? "EXT" : "INT", group_n); - } -#endif - - /* Set Combiner interrupt pending status after masking */ - if (group_n >= 32) { - s->icipsr[1] &= ~(1 << (group_n - 32)); - } else { - s->icipsr[0] &= ~(1 << group_n); - } - - qemu_irq_lower(s->output_irq[group_n]); - } -} - -static void exynos4210_combiner_write(void *opaque, hwaddr offset, - uint64_t val, unsigned size) -{ - struct Exynos4210CombinerState *s = - (struct Exynos4210CombinerState *)opaque; - uint32_t req_quad_base_n; /* Base of registers quad. Multiply it by 4 and - get a start of corresponding group quad */ - uint32_t grp_quad_base_n; /* Base of group quad */ - uint32_t reg_n; /* Register number inside the quad */ - - req_quad_base_n = offset >> 4; - grp_quad_base_n = req_quad_base_n << 2; - reg_n = (offset - (req_quad_base_n << 4)) >> 2; - - if (req_quad_base_n >= IIC_NGRP) { - hw_error("exynos4210.combiner: unallowed write access at offset 0x" - TARGET_FMT_plx "\n", offset); - return; - } - - if (reg_n > 1) { - hw_error("exynos4210.combiner: unallowed write access at offset 0x" - TARGET_FMT_plx "\n", offset); - return; - } - - if (offset >> 2 >= IIC_REGSET_SIZE) { - hw_error("exynos4210.combiner: overflow of reg_set by 0x" - TARGET_FMT_plx "offset\n", offset); - } - s->reg_set[offset >> 2] = val; - - switch (reg_n) { - /* IIESR */ - case 0: - /* FIXME: what if irq is pending, allowed by mask, and we allow it - * again. Interrupt will rise again! */ - - DPRINTF("%s enable IRQ for groups %d, %d, %d, %d\n", - s->external ? "EXT" : "INT", - grp_quad_base_n, - grp_quad_base_n + 1, - grp_quad_base_n + 2, - grp_quad_base_n + 3); - - /* Enable interrupt sources */ - s->group[grp_quad_base_n].src_mask |= val & 0xFF; - s->group[grp_quad_base_n + 1].src_mask |= (val & 0xFF00) >> 8; - s->group[grp_quad_base_n + 2].src_mask |= (val & 0xFF0000) >> 16; - s->group[grp_quad_base_n + 3].src_mask |= (val & 0xFF000000) >> 24; - - exynos4210_combiner_update(s, grp_quad_base_n); - exynos4210_combiner_update(s, grp_quad_base_n + 1); - exynos4210_combiner_update(s, grp_quad_base_n + 2); - exynos4210_combiner_update(s, grp_quad_base_n + 3); - break; - /* IIECR */ - case 1: - DPRINTF("%s disable IRQ for groups %d, %d, %d, %d\n", - s->external ? "EXT" : "INT", - grp_quad_base_n, - grp_quad_base_n + 1, - grp_quad_base_n + 2, - grp_quad_base_n + 3); - - /* Disable interrupt sources */ - s->group[grp_quad_base_n].src_mask &= ~(val & 0xFF); - s->group[grp_quad_base_n + 1].src_mask &= ~((val & 0xFF00) >> 8); - s->group[grp_quad_base_n + 2].src_mask &= ~((val & 0xFF0000) >> 16); - s->group[grp_quad_base_n + 3].src_mask &= ~((val & 0xFF000000) >> 24); - - exynos4210_combiner_update(s, grp_quad_base_n); - exynos4210_combiner_update(s, grp_quad_base_n + 1); - exynos4210_combiner_update(s, grp_quad_base_n + 2); - exynos4210_combiner_update(s, grp_quad_base_n + 3); - break; - default: - hw_error("exynos4210.combiner: unallowed write access at offset 0x" - TARGET_FMT_plx "\n", offset); - break; - } -} - -/* Get combiner group and bit from irq number */ -static uint8_t get_combiner_group_and_bit(int irq, uint8_t *bit) -{ - *bit = irq - ((irq >> 3) << 3); - return irq >> 3; -} - -/* Process a change in an external IRQ input. */ -static void exynos4210_combiner_handler(void *opaque, int irq, int level) -{ - struct Exynos4210CombinerState *s = - (struct Exynos4210CombinerState *)opaque; - uint8_t bit_n, group_n; - - group_n = get_combiner_group_and_bit(irq, &bit_n); - - if (s->external && group_n >= EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ) { - DPRINTF("%s unallowed IRQ group 0x%x\n", s->external ? "EXT" : "INT" - , group_n); - return; - } - - if (level) { - s->group[group_n].src_pending |= 1 << bit_n; - } else { - s->group[group_n].src_pending &= ~(1 << bit_n); - } - - exynos4210_combiner_update(s, group_n); -} - -static void exynos4210_combiner_reset(DeviceState *d) -{ - struct Exynos4210CombinerState *s = (struct Exynos4210CombinerState *)d; - - memset(&s->group, 0, sizeof(s->group)); - memset(&s->reg_set, 0, sizeof(s->reg_set)); - - s->reg_set[0xC0 >> 2] = 0x01010101; - s->reg_set[0xC4 >> 2] = 0x01010101; - s->reg_set[0xD0 >> 2] = 0x01010101; - s->reg_set[0xD4 >> 2] = 0x01010101; -} - -static const MemoryRegionOps exynos4210_combiner_ops = { - .read = exynos4210_combiner_read, - .write = exynos4210_combiner_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -/* - * Internal Combiner initialization. - */ -static int exynos4210_combiner_init(SysBusDevice *dev) -{ - unsigned int i; - struct Exynos4210CombinerState *s = - FROM_SYSBUS(struct Exynos4210CombinerState, dev); - - /* Allocate general purpose input signals and connect a handler to each of - * them */ - qdev_init_gpio_in(&s->busdev.qdev, exynos4210_combiner_handler, IIC_NIRQ); - - /* Connect SysBusDev irqs to device specific irqs */ - for (i = 0; i < IIC_NIRQ; i++) { - sysbus_init_irq(dev, &s->output_irq[i]); - } - - memory_region_init_io(&s->iomem, &exynos4210_combiner_ops, s, - "exynos4210-combiner", IIC_REGION_SIZE); - sysbus_init_mmio(dev, &s->iomem); - - return 0; -} - -static Property exynos4210_combiner_properties[] = { - DEFINE_PROP_UINT32("external", Exynos4210CombinerState, external, 0), - DEFINE_PROP_END_OF_LIST(), -}; - -static void exynos4210_combiner_class_init(ObjectClass *klass, void *data) -{ - DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = exynos4210_combiner_init; - dc->reset = exynos4210_combiner_reset; - dc->props = exynos4210_combiner_properties; - dc->vmsd = &vmstate_exynos4210_combiner; -} - -static const TypeInfo exynos4210_combiner_info = { - .name = "exynos4210.combiner", - .parent = TYPE_SYS_BUS_DEVICE, - .instance_size = sizeof(Exynos4210CombinerState), - .class_init = exynos4210_combiner_class_init, -}; - -static void exynos4210_combiner_register_types(void) -{ - type_register_static(&exynos4210_combiner_info); -} - -type_init(exynos4210_combiner_register_types) |