openpic: make register names correspond better with hw docs
The base openpic specification doesn't provide abbreviated register names, so it's somewhat understandable that the QEMU code made up its own, except that most of the names that QEMU used didn't correspond to the terminology used by any implementation I could find. In some cases, like PCTP, the phrase "processor current task priority" could be found in the openpic spec when describing the concept, but the register itself was labelled "current task priority register" and every implementation seems to use either CTPR or the full phrase. In other cases, individual implementations disagree on what to call the register. The implementations I have documentation for are Freescale, Raven (MCP750), and IBM. The Raven docs tend to not use abbreviations at all. The IBM MPIC isn't implemented in QEMU. Thus, where there's disagreement I chose to use the Freescale abbreviations. Signed-off-by: Scott Wood <scottwood@freescale.com> [agraf: rebase on current state of the code] Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
a1bb73849f
commit
be7c236fa2
352
hw/openpic.c
352
hw/openpic.c
@ -63,7 +63,7 @@ static const int debug_openpic = 0;
|
||||
#define VID 0x03 /* MPIC version ID */
|
||||
|
||||
/* OpenPIC capability flags */
|
||||
#define OPENPIC_FLAG_IDE_CRIT (1 << 0)
|
||||
#define OPENPIC_FLAG_IDR_CRIT (1 << 0)
|
||||
|
||||
/* OpenPIC address map */
|
||||
#define OPENPIC_GLB_REG_START 0x0
|
||||
@ -120,19 +120,19 @@ static const int debug_openpic = 0;
|
||||
#define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */
|
||||
#define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */
|
||||
|
||||
#define FREP_NIRQ_SHIFT 16
|
||||
#define FREP_NCPU_SHIFT 8
|
||||
#define FREP_VID_SHIFT 0
|
||||
#define FRR_NIRQ_SHIFT 16
|
||||
#define FRR_NCPU_SHIFT 8
|
||||
#define FRR_VID_SHIFT 0
|
||||
|
||||
#define VID_REVISION_1_2 2
|
||||
#define VID_REVISION_1_3 3
|
||||
|
||||
#define VENI_GENERIC 0x00000000 /* Generic Vendor ID */
|
||||
#define VIR_GENERIC 0x00000000 /* Generic Vendor ID */
|
||||
|
||||
#define GLBC_RESET 0x80000000
|
||||
#define GCR_RESET 0x80000000
|
||||
|
||||
#define TIBC_CI 0x80000000 /* count inhibit */
|
||||
#define TICC_TOG 0x80000000 /* toggles when decrement to zero */
|
||||
#define TBCR_CI 0x80000000 /* count inhibit */
|
||||
#define TCCR_TOG 0x80000000 /* toggles when decrement to zero */
|
||||
|
||||
#define IDR_EP_SHIFT 31
|
||||
#define IDR_EP_MASK (1 << IDR_EP_SHIFT)
|
||||
@ -187,33 +187,33 @@ typedef struct IRQQueue {
|
||||
} IRQQueue;
|
||||
|
||||
typedef struct IRQSource {
|
||||
uint32_t ipvp; /* IRQ vector/priority register */
|
||||
uint32_t ide; /* IRQ destination register */
|
||||
uint32_t ivpr; /* IRQ vector/priority register */
|
||||
uint32_t idr; /* IRQ destination register */
|
||||
int last_cpu;
|
||||
int pending; /* TRUE if IRQ is pending */
|
||||
} IRQSource;
|
||||
|
||||
#define IPVP_MASK_SHIFT 31
|
||||
#define IPVP_MASK_MASK (1 << IPVP_MASK_SHIFT)
|
||||
#define IPVP_ACTIVITY_SHIFT 30
|
||||
#define IPVP_ACTIVITY_MASK (1 << IPVP_ACTIVITY_SHIFT)
|
||||
#define IPVP_MODE_SHIFT 29
|
||||
#define IPVP_MODE_MASK (1 << IPVP_MODE_SHIFT)
|
||||
#define IPVP_POLARITY_SHIFT 23
|
||||
#define IPVP_POLARITY_MASK (1 << IPVP_POLARITY_SHIFT)
|
||||
#define IPVP_SENSE_SHIFT 22
|
||||
#define IPVP_SENSE_MASK (1 << IPVP_SENSE_SHIFT)
|
||||
#define IVPR_MASK_SHIFT 31
|
||||
#define IVPR_MASK_MASK (1 << IVPR_MASK_SHIFT)
|
||||
#define IVPR_ACTIVITY_SHIFT 30
|
||||
#define IVPR_ACTIVITY_MASK (1 << IVPR_ACTIVITY_SHIFT)
|
||||
#define IVPR_MODE_SHIFT 29
|
||||
#define IVPR_MODE_MASK (1 << IVPR_MODE_SHIFT)
|
||||
#define IVPR_POLARITY_SHIFT 23
|
||||
#define IVPR_POLARITY_MASK (1 << IVPR_POLARITY_SHIFT)
|
||||
#define IVPR_SENSE_SHIFT 22
|
||||
#define IVPR_SENSE_MASK (1 << IVPR_SENSE_SHIFT)
|
||||
|
||||
#define IPVP_PRIORITY_MASK (0xF << 16)
|
||||
#define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
|
||||
#define IPVP_VECTOR(opp, _ipvpr_) ((_ipvpr_) & (opp)->vector_mask)
|
||||
#define IVPR_PRIORITY_MASK (0xF << 16)
|
||||
#define IVPR_PRIORITY(_ivprr_) ((int)(((_ivprr_) & IVPR_PRIORITY_MASK) >> 16))
|
||||
#define IVPR_VECTOR(opp, _ivprr_) ((_ivprr_) & (opp)->vector_mask)
|
||||
|
||||
/* IDE[EP/CI] are only for FSL MPIC prior to v4.0 */
|
||||
#define IDE_EP 0x80000000 /* external pin */
|
||||
#define IDE_CI 0x40000000 /* critical interrupt */
|
||||
/* IDR[EP/CI] are only for FSL MPIC prior to v4.0 */
|
||||
#define IDR_EP 0x80000000 /* external pin */
|
||||
#define IDR_CI 0x40000000 /* critical interrupt */
|
||||
|
||||
typedef struct IRQDest {
|
||||
uint32_t pctp; /* CPU current task priority */
|
||||
uint32_t ctpr; /* CPU current task priority */
|
||||
IRQQueue raised;
|
||||
IRQQueue servicing;
|
||||
qemu_irq *irqs;
|
||||
@ -228,22 +228,22 @@ typedef struct OpenPICState {
|
||||
uint32_t flags;
|
||||
uint32_t nb_irqs;
|
||||
uint32_t vid;
|
||||
uint32_t veni; /* Vendor identification register */
|
||||
uint32_t vir; /* Vendor identification register */
|
||||
uint32_t vector_mask;
|
||||
uint32_t tifr_reset;
|
||||
uint32_t ipvp_reset;
|
||||
uint32_t ide_reset;
|
||||
uint32_t tfrr_reset;
|
||||
uint32_t ivpr_reset;
|
||||
uint32_t idr_reset;
|
||||
uint32_t brr1;
|
||||
|
||||
/* Sub-regions */
|
||||
MemoryRegion sub_io_mem[5];
|
||||
|
||||
/* Global registers */
|
||||
uint32_t frep; /* Feature reporting register */
|
||||
uint32_t glbc; /* Global configuration register */
|
||||
uint32_t pint; /* Processor initialization register */
|
||||
uint32_t frr; /* Feature reporting register */
|
||||
uint32_t gcr; /* Global configuration register */
|
||||
uint32_t pir; /* Processor initialization register */
|
||||
uint32_t spve; /* Spurious vector register */
|
||||
uint32_t tifr; /* Timer frequency reporting register */
|
||||
uint32_t tfrr; /* Timer frequency reporting register */
|
||||
/* Source registers */
|
||||
IRQSource src[MAX_IRQ];
|
||||
/* Local registers per output pin */
|
||||
@ -251,8 +251,8 @@ typedef struct OpenPICState {
|
||||
uint32_t nb_cpus;
|
||||
/* Timer registers */
|
||||
struct {
|
||||
uint32_t ticc; /* Global timer current count register */
|
||||
uint32_t tibc; /* Global timer base count register */
|
||||
uint32_t tccr; /* Global timer current count register */
|
||||
uint32_t tbcr; /* Global timer base count register */
|
||||
} timers[MAX_TMR];
|
||||
/* Shared MSI registers */
|
||||
struct {
|
||||
@ -298,11 +298,11 @@ static void IRQ_check(OpenPICState *opp, IRQQueue *q)
|
||||
|
||||
for (i = 0; i < opp->max_irq; i++) {
|
||||
if (IRQ_testbit(q, i)) {
|
||||
DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
|
||||
i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
|
||||
if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
|
||||
DPRINTF("IRQ_check: irq %d set ivpr_pr=%d pr=%d\n",
|
||||
i, IVPR_PRIORITY(opp->src[i].ivpr), priority);
|
||||
if (IVPR_PRIORITY(opp->src[i].ivpr) > priority) {
|
||||
next = i;
|
||||
priority = IPVP_PRIORITY(opp->src[i].ipvp);
|
||||
priority = IVPR_PRIORITY(opp->src[i].ivpr);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -330,8 +330,8 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
|
||||
|
||||
dst = &opp->dst[n_CPU];
|
||||
src = &opp->src[n_IRQ];
|
||||
priority = IPVP_PRIORITY(src->ipvp);
|
||||
if (priority <= dst->pctp) {
|
||||
priority = IVPR_PRIORITY(src->ivpr);
|
||||
if (priority <= dst->ctpr) {
|
||||
/* Too low priority */
|
||||
DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
|
||||
__func__, n_IRQ, n_CPU);
|
||||
@ -343,7 +343,7 @@ static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
|
||||
__func__, n_IRQ, n_CPU);
|
||||
return;
|
||||
}
|
||||
src->ipvp |= IPVP_ACTIVITY_MASK;
|
||||
src->ivpr |= IVPR_ACTIVITY_MASK;
|
||||
IRQ_setbit(&dst->raised, n_IRQ);
|
||||
if (priority < dst->raised.priority) {
|
||||
/* An higher priority IRQ is already raised */
|
||||
@ -376,34 +376,34 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
|
||||
DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
|
||||
return;
|
||||
}
|
||||
if (src->ipvp & IPVP_MASK_MASK) {
|
||||
if (src->ivpr & IVPR_MASK_MASK) {
|
||||
/* Interrupt source is disabled */
|
||||
DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
|
||||
return;
|
||||
}
|
||||
if (IPVP_PRIORITY(src->ipvp) == 0) {
|
||||
if (IVPR_PRIORITY(src->ivpr) == 0) {
|
||||
/* Priority set to zero */
|
||||
DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
|
||||
return;
|
||||
}
|
||||
if (src->ipvp & IPVP_ACTIVITY_MASK) {
|
||||
if (src->ivpr & IVPR_ACTIVITY_MASK) {
|
||||
/* IRQ already active */
|
||||
DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
|
||||
return;
|
||||
}
|
||||
if (src->ide == 0) {
|
||||
if (src->idr == 0) {
|
||||
/* No target */
|
||||
DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
|
||||
return;
|
||||
}
|
||||
|
||||
if (src->ide == (1 << src->last_cpu)) {
|
||||
if (src->idr == (1 << src->last_cpu)) {
|
||||
/* Only one CPU is allowed to receive this IRQ */
|
||||
IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
|
||||
} else if (!(src->ipvp & IPVP_MODE_MASK)) {
|
||||
} else if (!(src->ivpr & IVPR_MODE_MASK)) {
|
||||
/* Directed delivery mode */
|
||||
for (i = 0; i < opp->nb_cpus; i++) {
|
||||
if (src->ide & (1 << i)) {
|
||||
if (src->idr & (1 << i)) {
|
||||
IRQ_local_pipe(opp, i, n_IRQ);
|
||||
}
|
||||
}
|
||||
@ -413,7 +413,7 @@ static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
|
||||
if (i == opp->nb_cpus) {
|
||||
i = 0;
|
||||
}
|
||||
if (src->ide & (1 << i)) {
|
||||
if (src->idr & (1 << i)) {
|
||||
IRQ_local_pipe(opp, i, n_IRQ);
|
||||
src->last_cpu = i;
|
||||
break;
|
||||
@ -428,13 +428,13 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
|
||||
IRQSource *src;
|
||||
|
||||
src = &opp->src[n_IRQ];
|
||||
DPRINTF("openpic: set irq %d = %d ipvp=0x%08x\n",
|
||||
n_IRQ, level, src->ipvp);
|
||||
if (src->ipvp & IPVP_SENSE_MASK) {
|
||||
DPRINTF("openpic: set irq %d = %d ivpr=0x%08x\n",
|
||||
n_IRQ, level, src->ivpr);
|
||||
if (src->ivpr & IVPR_SENSE_MASK) {
|
||||
/* level-sensitive irq */
|
||||
src->pending = level;
|
||||
if (!level) {
|
||||
src->ipvp &= ~IPVP_ACTIVITY_MASK;
|
||||
src->ivpr &= ~IVPR_ACTIVITY_MASK;
|
||||
}
|
||||
} else {
|
||||
/* edge-sensitive irq */
|
||||
@ -450,23 +450,23 @@ static void openpic_reset(DeviceState *d)
|
||||
OpenPICState *opp = FROM_SYSBUS(typeof (*opp), sysbus_from_qdev(d));
|
||||
int i;
|
||||
|
||||
opp->glbc = GLBC_RESET;
|
||||
opp->gcr = GCR_RESET;
|
||||
/* Initialise controller registers */
|
||||
opp->frep = ((opp->nb_irqs - 1) << FREP_NIRQ_SHIFT) |
|
||||
((opp->nb_cpus - 1) << FREP_NCPU_SHIFT) |
|
||||
(opp->vid << FREP_VID_SHIFT);
|
||||
opp->frr = ((opp->nb_irqs - 1) << FRR_NIRQ_SHIFT) |
|
||||
((opp->nb_cpus - 1) << FRR_NCPU_SHIFT) |
|
||||
(opp->vid << FRR_VID_SHIFT);
|
||||
|
||||
opp->pint = 0;
|
||||
opp->pir = 0;
|
||||
opp->spve = -1 & opp->vector_mask;
|
||||
opp->tifr = opp->tifr_reset;
|
||||
opp->tfrr = opp->tfrr_reset;
|
||||
/* Initialise IRQ sources */
|
||||
for (i = 0; i < opp->max_irq; i++) {
|
||||
opp->src[i].ipvp = opp->ipvp_reset;
|
||||
opp->src[i].ide = opp->ide_reset;
|
||||
opp->src[i].ivpr = opp->ivpr_reset;
|
||||
opp->src[i].idr = opp->idr_reset;
|
||||
}
|
||||
/* Initialise IRQ destinations */
|
||||
for (i = 0; i < MAX_CPU; i++) {
|
||||
opp->dst[i].pctp = 15;
|
||||
opp->dst[i].ctpr = 15;
|
||||
memset(&opp->dst[i].raised, 0, sizeof(IRQQueue));
|
||||
opp->dst[i].raised.next = -1;
|
||||
memset(&opp->dst[i].servicing, 0, sizeof(IRQQueue));
|
||||
@ -474,42 +474,42 @@ static void openpic_reset(DeviceState *d)
|
||||
}
|
||||
/* Initialise timers */
|
||||
for (i = 0; i < MAX_TMR; i++) {
|
||||
opp->timers[i].ticc = 0;
|
||||
opp->timers[i].tibc = TIBC_CI;
|
||||
opp->timers[i].tccr = 0;
|
||||
opp->timers[i].tbcr = TBCR_CI;
|
||||
}
|
||||
/* Go out of RESET state */
|
||||
opp->glbc = 0;
|
||||
opp->gcr = 0;
|
||||
}
|
||||
|
||||
static inline uint32_t read_IRQreg_ide(OpenPICState *opp, int n_IRQ)
|
||||
static inline uint32_t read_IRQreg_idr(OpenPICState *opp, int n_IRQ)
|
||||
{
|
||||
return opp->src[n_IRQ].ide;
|
||||
return opp->src[n_IRQ].idr;
|
||||
}
|
||||
|
||||
static inline uint32_t read_IRQreg_ipvp(OpenPICState *opp, int n_IRQ)
|
||||
static inline uint32_t read_IRQreg_ivpr(OpenPICState *opp, int n_IRQ)
|
||||
{
|
||||
return opp->src[n_IRQ].ipvp;
|
||||
return opp->src[n_IRQ].ivpr;
|
||||
}
|
||||
|
||||
static inline void write_IRQreg_ide(OpenPICState *opp, int n_IRQ, uint32_t val)
|
||||
static inline void write_IRQreg_idr(OpenPICState *opp, int n_IRQ, uint32_t val)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = val & (IDE_EP | IDE_CI);
|
||||
tmp = val & (IDR_EP | IDR_CI);
|
||||
tmp |= val & ((1ULL << MAX_CPU) - 1);
|
||||
opp->src[n_IRQ].ide = tmp;
|
||||
DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
|
||||
opp->src[n_IRQ].idr = tmp;
|
||||
DPRINTF("Set IDR %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].idr);
|
||||
}
|
||||
|
||||
static inline void write_IRQreg_ipvp(OpenPICState *opp, int n_IRQ, uint32_t val)
|
||||
static inline void write_IRQreg_ivpr(OpenPICState *opp, int n_IRQ, uint32_t val)
|
||||
{
|
||||
/* NOTE: not fully accurate for special IRQs, but simple and sufficient */
|
||||
/* ACTIVITY bit is read-only */
|
||||
opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & IPVP_ACTIVITY_MASK) |
|
||||
(val & (IPVP_MASK_MASK | IPVP_PRIORITY_MASK | opp->vector_mask));
|
||||
opp->src[n_IRQ].ivpr = (opp->src[n_IRQ].ivpr & IVPR_ACTIVITY_MASK) |
|
||||
(val & (IVPR_MASK_MASK | IVPR_PRIORITY_MASK | opp->vector_mask));
|
||||
openpic_update_irq(opp, n_IRQ);
|
||||
DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
|
||||
opp->src[n_IRQ].ipvp);
|
||||
DPRINTF("Set IVPR %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
|
||||
opp->src[n_IRQ].ivpr);
|
||||
}
|
||||
|
||||
static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
@ -537,37 +537,37 @@ static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
case 0xB0:
|
||||
openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
|
||||
break;
|
||||
case 0x1000: /* FREP */
|
||||
case 0x1000: /* FRR */
|
||||
break;
|
||||
case 0x1020: /* GLBC */
|
||||
if (val & GLBC_RESET) {
|
||||
case 0x1020: /* GCR */
|
||||
if (val & GCR_RESET) {
|
||||
openpic_reset(&opp->busdev.qdev);
|
||||
}
|
||||
break;
|
||||
case 0x1080: /* VENI */
|
||||
case 0x1080: /* VIR */
|
||||
break;
|
||||
case 0x1090: /* PINT */
|
||||
case 0x1090: /* PIR */
|
||||
for (idx = 0; idx < opp->nb_cpus; idx++) {
|
||||
if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
|
||||
if ((val & (1 << idx)) && !(opp->pir & (1 << idx))) {
|
||||
DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
|
||||
dst = &opp->dst[idx];
|
||||
qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
|
||||
} else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
|
||||
} else if (!(val & (1 << idx)) && (opp->pir & (1 << idx))) {
|
||||
DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
|
||||
dst = &opp->dst[idx];
|
||||
qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
|
||||
}
|
||||
}
|
||||
opp->pint = val;
|
||||
opp->pir = val;
|
||||
break;
|
||||
case 0x10A0: /* IPI_IPVP */
|
||||
case 0x10A0: /* IPI_IVPR */
|
||||
case 0x10B0:
|
||||
case 0x10C0:
|
||||
case 0x10D0:
|
||||
{
|
||||
int idx;
|
||||
idx = (addr - 0x10A0) >> 4;
|
||||
write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
|
||||
write_IRQreg_ivpr(opp, opp->irq_ipi0 + idx, val);
|
||||
}
|
||||
break;
|
||||
case 0x10E0: /* SPVE */
|
||||
@ -589,16 +589,16 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
|
||||
return retval;
|
||||
}
|
||||
switch (addr) {
|
||||
case 0x1000: /* FREP */
|
||||
retval = opp->frep;
|
||||
case 0x1000: /* FRR */
|
||||
retval = opp->frr;
|
||||
break;
|
||||
case 0x1020: /* GLBC */
|
||||
retval = opp->glbc;
|
||||
case 0x1020: /* GCR */
|
||||
retval = opp->gcr;
|
||||
break;
|
||||
case 0x1080: /* VENI */
|
||||
retval = opp->veni;
|
||||
case 0x1080: /* VIR */
|
||||
retval = opp->vir;
|
||||
break;
|
||||
case 0x1090: /* PINT */
|
||||
case 0x1090: /* PIR */
|
||||
retval = 0x00000000;
|
||||
break;
|
||||
case 0x00: /* Block Revision Register1 (BRR1) */
|
||||
@ -614,14 +614,14 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
|
||||
case 0xB0:
|
||||
retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
|
||||
break;
|
||||
case 0x10A0: /* IPI_IPVP */
|
||||
case 0x10A0: /* IPI_IVPR */
|
||||
case 0x10B0:
|
||||
case 0x10C0:
|
||||
case 0x10D0:
|
||||
{
|
||||
int idx;
|
||||
idx = (addr - 0x10A0) >> 4;
|
||||
retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
|
||||
retval = read_IRQreg_ivpr(opp, opp->irq_ipi0 + idx);
|
||||
}
|
||||
break;
|
||||
case 0x10E0: /* SPVE */
|
||||
@ -650,26 +650,26 @@ static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
addr = addr & 0x30;
|
||||
|
||||
if (addr == 0x0) {
|
||||
/* TIFR (TFRR) */
|
||||
opp->tifr = val;
|
||||
/* TFRR */
|
||||
opp->tfrr = val;
|
||||
return;
|
||||
}
|
||||
switch (addr & 0x30) {
|
||||
case 0x00: /* TICC (GTCCR) */
|
||||
case 0x00: /* TCCR */
|
||||
break;
|
||||
case 0x10: /* TIBC (GTBCR) */
|
||||
if ((opp->timers[idx].ticc & TICC_TOG) != 0 &&
|
||||
(val & TIBC_CI) == 0 &&
|
||||
(opp->timers[idx].tibc & TIBC_CI) != 0) {
|
||||
opp->timers[idx].ticc &= ~TICC_TOG;
|
||||
case 0x10: /* TBCR */
|
||||
if ((opp->timers[idx].tccr & TCCR_TOG) != 0 &&
|
||||
(val & TBCR_CI) == 0 &&
|
||||
(opp->timers[idx].tbcr & TBCR_CI) != 0) {
|
||||
opp->timers[idx].tccr &= ~TCCR_TOG;
|
||||
}
|
||||
opp->timers[idx].tibc = val;
|
||||
opp->timers[idx].tbcr = val;
|
||||
break;
|
||||
case 0x20: /* TIVP (GTIVPR) */
|
||||
write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
|
||||
case 0x20: /* TVPR */
|
||||
write_IRQreg_ivpr(opp, opp->irq_tim0 + idx, val);
|
||||
break;
|
||||
case 0x30: /* TIDE (GTIDR) */
|
||||
write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
|
||||
case 0x30: /* TDR */
|
||||
write_IRQreg_idr(opp, opp->irq_tim0 + idx, val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -686,22 +686,22 @@ static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
|
||||
}
|
||||
idx = (addr >> 6) & 0x3;
|
||||
if (addr == 0x0) {
|
||||
/* TIFR (TFRR) */
|
||||
retval = opp->tifr;
|
||||
/* TFRR */
|
||||
retval = opp->tfrr;
|
||||
goto out;
|
||||
}
|
||||
switch (addr & 0x30) {
|
||||
case 0x00: /* TICC (GTCCR) */
|
||||
retval = opp->timers[idx].ticc;
|
||||
case 0x00: /* TCCR */
|
||||
retval = opp->timers[idx].tccr;
|
||||
break;
|
||||
case 0x10: /* TIBC (GTBCR) */
|
||||
retval = opp->timers[idx].tibc;
|
||||
case 0x10: /* TBCR */
|
||||
retval = opp->timers[idx].tbcr;
|
||||
break;
|
||||
case 0x20: /* TIPV (TIPV) */
|
||||
retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
|
||||
case 0x20: /* TIPV */
|
||||
retval = read_IRQreg_ivpr(opp, opp->irq_tim0 + idx);
|
||||
break;
|
||||
case 0x30: /* TIDE (TIDR) */
|
||||
retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
|
||||
retval = read_IRQreg_idr(opp, opp->irq_tim0 + idx);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -726,10 +726,10 @@ static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
|
||||
idx = addr >> 5;
|
||||
if (addr & 0x10) {
|
||||
/* EXDE / IFEDE / IEEDE */
|
||||
write_IRQreg_ide(opp, idx, val);
|
||||
write_IRQreg_idr(opp, idx, val);
|
||||
} else {
|
||||
/* EXVP / IFEVP / IEEVP */
|
||||
write_IRQreg_ipvp(opp, idx, val);
|
||||
write_IRQreg_ivpr(opp, idx, val);
|
||||
}
|
||||
}
|
||||
|
||||
@ -748,10 +748,10 @@ static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
|
||||
idx = addr >> 5;
|
||||
if (addr & 0x10) {
|
||||
/* EXDE / IFEDE / IEEDE */
|
||||
retval = read_IRQreg_ide(opp, idx);
|
||||
retval = read_IRQreg_idr(opp, idx);
|
||||
} else {
|
||||
/* EXVP / IFEVP / IEEVP */
|
||||
retval = read_IRQreg_ipvp(opp, idx);
|
||||
retval = read_IRQreg_ivpr(opp, idx);
|
||||
}
|
||||
DPRINTF("%s: => 0x%08x\n", __func__, retval);
|
||||
|
||||
@ -849,22 +849,22 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
|
||||
case 0x70:
|
||||
idx = (addr - 0x40) >> 4;
|
||||
/* we use IDE as mask which CPUs to deliver the IPI to still. */
|
||||
write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
|
||||
opp->src[opp->irq_ipi0 + idx].ide | val);
|
||||
write_IRQreg_idr(opp, opp->irq_ipi0 + idx,
|
||||
opp->src[opp->irq_ipi0 + idx].idr | val);
|
||||
openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
|
||||
openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
|
||||
break;
|
||||
case 0x80: /* PCTP */
|
||||
dst->pctp = val & 0x0000000F;
|
||||
case 0x80: /* CTPR */
|
||||
dst->ctpr = val & 0x0000000F;
|
||||
break;
|
||||
case 0x90: /* WHOAMI */
|
||||
/* Read-only register */
|
||||
break;
|
||||
case 0xA0: /* PIAC */
|
||||
case 0xA0: /* IACK */
|
||||
/* Read-only register */
|
||||
break;
|
||||
case 0xB0: /* PEOI */
|
||||
DPRINTF("PEOI\n");
|
||||
case 0xB0: /* EOI */
|
||||
DPRINTF("EOI\n");
|
||||
s_IRQ = IRQ_get_next(opp, &dst->servicing);
|
||||
IRQ_resetbit(&dst->servicing, s_IRQ);
|
||||
dst->servicing.next = -1;
|
||||
@ -875,7 +875,7 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
|
||||
src = &opp->src[n_IRQ];
|
||||
if (n_IRQ != -1 &&
|
||||
(s_IRQ == -1 ||
|
||||
IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
|
||||
IVPR_PRIORITY(src->ivpr) > dst->servicing.priority)) {
|
||||
DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
|
||||
idx, n_IRQ);
|
||||
openpic_irq_raise(opp, idx, src);
|
||||
@ -914,56 +914,56 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
|
||||
dst = &opp->dst[idx];
|
||||
addr &= 0xFF0;
|
||||
switch (addr) {
|
||||
case 0x80: /* PCTP */
|
||||
retval = dst->pctp;
|
||||
case 0x80: /* CTPR */
|
||||
retval = dst->ctpr;
|
||||
break;
|
||||
case 0x90: /* WHOAMI */
|
||||
retval = idx;
|
||||
break;
|
||||
case 0xA0: /* PIAC */
|
||||
case 0xA0: /* IACK */
|
||||
DPRINTF("Lower OpenPIC INT output\n");
|
||||
qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
|
||||
n_IRQ = IRQ_get_next(opp, &dst->raised);
|
||||
DPRINTF("PIAC: irq=%d\n", n_IRQ);
|
||||
DPRINTF("IACK: irq=%d\n", n_IRQ);
|
||||
if (n_IRQ == -1) {
|
||||
/* No more interrupt pending */
|
||||
retval = opp->spve;
|
||||
} else {
|
||||
src = &opp->src[n_IRQ];
|
||||
if (!(src->ipvp & IPVP_ACTIVITY_MASK) ||
|
||||
!(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
|
||||
if (!(src->ivpr & IVPR_ACTIVITY_MASK) ||
|
||||
!(IVPR_PRIORITY(src->ivpr) > dst->ctpr)) {
|
||||
/* - Spurious level-sensitive IRQ
|
||||
* - Priorities has been changed
|
||||
* and the pending IRQ isn't allowed anymore
|
||||
*/
|
||||
src->ipvp &= ~IPVP_ACTIVITY_MASK;
|
||||
src->ivpr &= ~IVPR_ACTIVITY_MASK;
|
||||
retval = opp->spve;
|
||||
} else {
|
||||
/* IRQ enter servicing state */
|
||||
IRQ_setbit(&dst->servicing, n_IRQ);
|
||||
retval = IPVP_VECTOR(opp, src->ipvp);
|
||||
retval = IVPR_VECTOR(opp, src->ivpr);
|
||||
}
|
||||
IRQ_resetbit(&dst->raised, n_IRQ);
|
||||
dst->raised.next = -1;
|
||||
if (!(src->ipvp & IPVP_SENSE_MASK)) {
|
||||
if (!(src->ivpr & IVPR_SENSE_MASK)) {
|
||||
/* edge-sensitive IRQ */
|
||||
src->ipvp &= ~IPVP_ACTIVITY_MASK;
|
||||
src->ivpr &= ~IVPR_ACTIVITY_MASK;
|
||||
src->pending = 0;
|
||||
}
|
||||
|
||||
if ((n_IRQ >= opp->irq_ipi0) && (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
|
||||
src->ide &= ~(1 << idx);
|
||||
if (src->ide && !(src->ipvp & IPVP_SENSE_MASK)) {
|
||||
src->idr &= ~(1 << idx);
|
||||
if (src->idr && !(src->ivpr & IVPR_SENSE_MASK)) {
|
||||
/* trigger on CPUs that didn't know about it yet */
|
||||
openpic_set_irq(opp, n_IRQ, 1);
|
||||
openpic_set_irq(opp, n_IRQ, 0);
|
||||
/* if all CPUs knew about it, set active bit again */
|
||||
src->ipvp |= IPVP_ACTIVITY_MASK;
|
||||
src->ivpr |= IVPR_ACTIVITY_MASK;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0xB0: /* PEOI */
|
||||
case 0xB0: /* EOI */
|
||||
retval = 0;
|
||||
break;
|
||||
default:
|
||||
@ -1095,15 +1095,15 @@ static void openpic_save(QEMUFile* f, void *opaque)
|
||||
OpenPICState *opp = (OpenPICState *)opaque;
|
||||
unsigned int i;
|
||||
|
||||
qemu_put_be32s(f, &opp->glbc);
|
||||
qemu_put_be32s(f, &opp->veni);
|
||||
qemu_put_be32s(f, &opp->pint);
|
||||
qemu_put_be32s(f, &opp->gcr);
|
||||
qemu_put_be32s(f, &opp->vir);
|
||||
qemu_put_be32s(f, &opp->pir);
|
||||
qemu_put_be32s(f, &opp->spve);
|
||||
qemu_put_be32s(f, &opp->tifr);
|
||||
qemu_put_be32s(f, &opp->tfrr);
|
||||
|
||||
for (i = 0; i < opp->max_irq; i++) {
|
||||
qemu_put_be32s(f, &opp->src[i].ipvp);
|
||||
qemu_put_be32s(f, &opp->src[i].ide);
|
||||
qemu_put_be32s(f, &opp->src[i].ivpr);
|
||||
qemu_put_be32s(f, &opp->src[i].idr);
|
||||
qemu_put_sbe32s(f, &opp->src[i].last_cpu);
|
||||
qemu_put_sbe32s(f, &opp->src[i].pending);
|
||||
}
|
||||
@ -1111,14 +1111,14 @@ static void openpic_save(QEMUFile* f, void *opaque)
|
||||
qemu_put_be32s(f, &opp->nb_cpus);
|
||||
|
||||
for (i = 0; i < opp->nb_cpus; i++) {
|
||||
qemu_put_be32s(f, &opp->dst[i].pctp);
|
||||
qemu_put_be32s(f, &opp->dst[i].ctpr);
|
||||
openpic_save_IRQ_queue(f, &opp->dst[i].raised);
|
||||
openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_TMR; i++) {
|
||||
qemu_put_be32s(f, &opp->timers[i].ticc);
|
||||
qemu_put_be32s(f, &opp->timers[i].tibc);
|
||||
qemu_put_be32s(f, &opp->timers[i].tccr);
|
||||
qemu_put_be32s(f, &opp->timers[i].tbcr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1142,15 +1142,15 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
qemu_get_be32s(f, &opp->glbc);
|
||||
qemu_get_be32s(f, &opp->veni);
|
||||
qemu_get_be32s(f, &opp->pint);
|
||||
qemu_get_be32s(f, &opp->gcr);
|
||||
qemu_get_be32s(f, &opp->vir);
|
||||
qemu_get_be32s(f, &opp->pir);
|
||||
qemu_get_be32s(f, &opp->spve);
|
||||
qemu_get_be32s(f, &opp->tifr);
|
||||
qemu_get_be32s(f, &opp->tfrr);
|
||||
|
||||
for (i = 0; i < opp->max_irq; i++) {
|
||||
qemu_get_be32s(f, &opp->src[i].ipvp);
|
||||
qemu_get_be32s(f, &opp->src[i].ide);
|
||||
qemu_get_be32s(f, &opp->src[i].ivpr);
|
||||
qemu_get_be32s(f, &opp->src[i].idr);
|
||||
qemu_get_sbe32s(f, &opp->src[i].last_cpu);
|
||||
qemu_get_sbe32s(f, &opp->src[i].pending);
|
||||
}
|
||||
@ -1158,14 +1158,14 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
|
||||
qemu_get_be32s(f, &opp->nb_cpus);
|
||||
|
||||
for (i = 0; i < opp->nb_cpus; i++) {
|
||||
qemu_get_be32s(f, &opp->dst[i].pctp);
|
||||
qemu_get_be32s(f, &opp->dst[i].ctpr);
|
||||
openpic_load_IRQ_queue(f, &opp->dst[i].raised);
|
||||
openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
|
||||
}
|
||||
|
||||
for (i = 0; i < MAX_TMR; i++) {
|
||||
qemu_get_be32s(f, &opp->timers[i].ticc);
|
||||
qemu_get_be32s(f, &opp->timers[i].tibc);
|
||||
qemu_get_be32s(f, &opp->timers[i].tccr);
|
||||
qemu_get_be32s(f, &opp->timers[i].tbcr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -1175,7 +1175,7 @@ static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQSource *src)
|
||||
{
|
||||
int n_ci = IDR_CI0_SHIFT - n_CPU;
|
||||
|
||||
if ((opp->flags & OPENPIC_FLAG_IDE_CRIT) && (src->ide & (1 << n_ci))) {
|
||||
if ((opp->flags & OPENPIC_FLAG_IDR_CRIT) && (src->idr & (1 << n_ci))) {
|
||||
qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
|
||||
} else {
|
||||
qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
|
||||
@ -1223,14 +1223,14 @@ static int openpic_init(SysBusDevice *dev)
|
||||
switch (opp->model) {
|
||||
case OPENPIC_MODEL_FSL_MPIC_20:
|
||||
default:
|
||||
opp->flags |= OPENPIC_FLAG_IDE_CRIT;
|
||||
opp->flags |= OPENPIC_FLAG_IDR_CRIT;
|
||||
opp->nb_irqs = 80;
|
||||
opp->vid = VID_REVISION_1_2;
|
||||
opp->veni = VENI_GENERIC;
|
||||
opp->vir = VIR_GENERIC;
|
||||
opp->vector_mask = 0xFFFF;
|
||||
opp->tifr_reset = 0;
|
||||
opp->ipvp_reset = IPVP_MASK_MASK;
|
||||
opp->ide_reset = 1 << 0;
|
||||
opp->tfrr_reset = 0;
|
||||
opp->ivpr_reset = IVPR_MASK_MASK;
|
||||
opp->idr_reset = 1 << 0;
|
||||
opp->max_irq = FSL_MPIC_20_MAX_IRQ;
|
||||
opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ;
|
||||
opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ;
|
||||
@ -1242,11 +1242,11 @@ static int openpic_init(SysBusDevice *dev)
|
||||
case OPENPIC_MODEL_RAVEN:
|
||||
opp->nb_irqs = RAVEN_MAX_EXT;
|
||||
opp->vid = VID_REVISION_1_3;
|
||||
opp->veni = VENI_GENERIC;
|
||||
opp->vir = VIR_GENERIC;
|
||||
opp->vector_mask = 0xFF;
|
||||
opp->tifr_reset = 4160000;
|
||||
opp->ipvp_reset = IPVP_MASK_MASK | IPVP_MODE_MASK;
|
||||
opp->ide_reset = 0;
|
||||
opp->tfrr_reset = 4160000;
|
||||
opp->ivpr_reset = IVPR_MASK_MASK | IVPR_MODE_MASK;
|
||||
opp->idr_reset = 0;
|
||||
opp->max_irq = RAVEN_MAX_IRQ;
|
||||
opp->irq_ipi0 = RAVEN_IPI_IRQ;
|
||||
opp->irq_tim0 = RAVEN_TMR_IRQ;
|
||||
|
Loading…
Reference in New Issue
Block a user