Revision 825463b3 hw/openpic.c
b/hw/openpic.c | ||
---|---|---|
53 | 53 |
#define MAX_IPI 4 |
54 | 54 |
#define MAX_IRQ (MAX_SRC + MAX_IPI + MAX_TMR) |
55 | 55 |
#define VID 0x03 /* MPIC version ID */ |
56 |
#define VENI 0x00000000 /* Vendor ID */ |
|
57 | 56 |
|
58 | 57 |
enum { |
59 | 58 |
IRQ_IPVP = 0, |
... | ... | |
125 | 124 |
#define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */ |
126 | 125 |
#define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */ |
127 | 126 |
|
127 |
#define FREP_NIRQ_SHIFT 16 |
|
128 |
#define FREP_NCPU_SHIFT 8 |
|
129 |
#define FREP_VID_SHIFT 0 |
|
130 |
|
|
131 |
#define VID_REVISION_1_2 2 |
|
132 |
|
|
133 |
#define VENI_GENERIC 0x00000000 /* Generic Vendor ID */ |
|
134 |
|
|
128 | 135 |
enum mpic_ide_bits { |
129 | 136 |
IDR_EP = 31, |
130 | 137 |
IDR_CI0 = 30, |
... | ... | |
208 | 215 |
|
209 | 216 |
/* Behavior control */ |
210 | 217 |
uint32_t flags; |
218 |
uint32_t nb_irqs; |
|
219 |
uint32_t vid; |
|
220 |
uint32_t veni; /* Vendor identification register */ |
|
221 |
uint32_t spve_mask; |
|
222 |
uint32_t tifr_reset; |
|
223 |
uint32_t ipvp_reset; |
|
224 |
uint32_t ide_reset; |
|
211 | 225 |
|
212 | 226 |
/* Sub-regions */ |
213 | 227 |
MemoryRegion sub_io_mem[7]; |
... | ... | |
215 | 229 |
/* Global registers */ |
216 | 230 |
uint32_t frep; /* Feature reporting register */ |
217 | 231 |
uint32_t glbc; /* Global configuration register */ |
218 |
uint32_t micr; /* MPIC interrupt configuration register */ |
|
219 |
uint32_t veni; /* Vendor identification register */ |
|
220 | 232 |
uint32_t pint; /* Processor initialization register */ |
221 | 233 |
uint32_t spve; /* Spurious vector register */ |
222 | 234 |
uint32_t tifr; /* Timer frequency reporting register */ |
... | ... | |
235 | 247 |
int max_irq; |
236 | 248 |
int irq_ipi0; |
237 | 249 |
int irq_tim0; |
238 |
void (*reset) (void *); |
|
239 | 250 |
} openpic_t; |
240 | 251 |
|
241 | 252 |
static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src); |
... | ... | |
412 | 423 |
|
413 | 424 |
opp->glbc = 0x80000000; |
414 | 425 |
/* Initialise controller registers */ |
415 |
opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID; |
|
416 |
opp->veni = VENI; |
|
426 |
opp->frep = ((opp->nb_irqs -1) << FREP_NIRQ_SHIFT) | |
|
427 |
((opp->nb_cpus -1) << FREP_NCPU_SHIFT) | |
|
428 |
(opp->vid << FREP_VID_SHIFT); |
|
429 |
|
|
417 | 430 |
opp->pint = 0x00000000; |
418 |
opp->spve = 0x000000FF; |
|
419 |
opp->tifr = 0x003F7A00; |
|
420 |
/* ? */ |
|
421 |
opp->micr = 0x00000000; |
|
431 |
opp->spve = -1 & opp->spve_mask; |
|
432 |
opp->tifr = opp->tifr_reset; |
|
422 | 433 |
/* Initialise IRQ sources */ |
423 | 434 |
for (i = 0; i < opp->max_irq; i++) { |
424 |
opp->src[i].ipvp = 0xA0000000;
|
|
425 |
opp->src[i].ide = 0x00000000;
|
|
435 |
opp->src[i].ipvp = opp->ipvp_reset;
|
|
436 |
opp->src[i].ide = opp->ide_reset;
|
|
426 | 437 |
} |
427 | 438 |
/* Initialise IRQ destinations */ |
428 | 439 |
for (i = 0; i < MAX_CPU; i++) { |
... | ... | |
499 | 510 |
case 0x1000: /* FREP */ |
500 | 511 |
break; |
501 | 512 |
case 0x1020: /* GLBC */ |
502 |
if (val & 0x80000000 && opp->reset)
|
|
503 |
opp->reset(opp);
|
|
504 |
opp->glbc = val & ~0x80000000;
|
|
513 |
if (val & 0x80000000) {
|
|
514 |
openpic_reset(opp);
|
|
515 |
}
|
|
505 | 516 |
break; |
506 | 517 |
case 0x1080: /* VENI */ |
507 | 518 |
break; |
... | ... | |
530 | 541 |
} |
531 | 542 |
break; |
532 | 543 |
case 0x10E0: /* SPVE */ |
533 |
opp->spve = val & 0x000000FF;
|
|
544 |
opp->spve = val & opp->spve_mask;
|
|
534 | 545 |
break; |
535 | 546 |
default: |
536 | 547 |
break; |
... | ... | |
912 | 923 |
openpic_t *opp = (openpic_t *)opaque; |
913 | 924 |
unsigned int i; |
914 | 925 |
|
915 |
qemu_put_be32s(f, &opp->frep); |
|
916 | 926 |
qemu_put_be32s(f, &opp->glbc); |
917 |
qemu_put_be32s(f, &opp->micr); |
|
918 | 927 |
qemu_put_be32s(f, &opp->veni); |
919 | 928 |
qemu_put_be32s(f, &opp->pint); |
920 | 929 |
qemu_put_be32s(f, &opp->spve); |
... | ... | |
964 | 973 |
if (version_id != 1) |
965 | 974 |
return -EINVAL; |
966 | 975 |
|
967 |
qemu_get_be32s(f, &opp->frep); |
|
968 | 976 |
qemu_get_be32s(f, &opp->glbc); |
969 |
qemu_get_be32s(f, &opp->micr); |
|
970 | 977 |
qemu_get_be32s(f, &opp->veni); |
971 | 978 |
qemu_get_be32s(f, &opp->pint); |
972 | 979 |
qemu_get_be32s(f, &opp->spve); |
... | ... | |
1043 | 1050 |
|
1044 | 1051 |
// isu_base &= 0xFFFC0000; |
1045 | 1052 |
opp->nb_cpus = nb_cpus; |
1053 |
opp->nb_irqs = OPENPIC_EXT_IRQ; |
|
1054 |
opp->vid = VID; |
|
1055 |
opp->veni = VENI_GENERIC; |
|
1056 |
opp->spve_mask = 0xFF; |
|
1057 |
opp->tifr_reset = 0x003F7A00; |
|
1046 | 1058 |
opp->max_irq = OPENPIC_MAX_IRQ; |
1047 | 1059 |
opp->irq_ipi0 = OPENPIC_IRQ_IPI0; |
1048 | 1060 |
opp->irq_tim0 = OPENPIC_IRQ_TIM0; |
... | ... | |
1068 | 1080 |
openpic_save, openpic_load, opp); |
1069 | 1081 |
qemu_register_reset(openpic_reset, opp); |
1070 | 1082 |
|
1071 |
opp->reset = openpic_reset; |
|
1072 |
|
|
1073 | 1083 |
if (pmem) |
1074 | 1084 |
*pmem = &opp->mem; |
1075 | 1085 |
|
1076 | 1086 |
return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq); |
1077 | 1087 |
} |
1078 | 1088 |
|
1079 |
static void mpic_reset (void *opaque) |
|
1080 |
{ |
|
1081 |
openpic_t *mpp = (openpic_t *)opaque; |
|
1082 |
int i; |
|
1083 |
|
|
1084 |
mpp->glbc = 0x80000000; |
|
1085 |
/* Initialise controller registers */ |
|
1086 |
mpp->frep = 0x004f0002 | ((mpp->nb_cpus - 1) << 8); |
|
1087 |
mpp->veni = VENI; |
|
1088 |
mpp->pint = 0x00000000; |
|
1089 |
mpp->spve = 0x0000FFFF; |
|
1090 |
/* Initialise IRQ sources */ |
|
1091 |
for (i = 0; i < mpp->max_irq; i++) { |
|
1092 |
mpp->src[i].ipvp = 0x80800000; |
|
1093 |
mpp->src[i].ide = 0x00000001; |
|
1094 |
} |
|
1095 |
/* Set IDE for IPIs to 0 so we don't get spurious interrupts */ |
|
1096 |
for (i = mpp->irq_ipi0; i < (mpp->irq_ipi0 + MAX_IPI); i++) { |
|
1097 |
mpp->src[i].ide = 0; |
|
1098 |
} |
|
1099 |
/* Initialise IRQ destinations */ |
|
1100 |
for (i = 0; i < MAX_CPU; i++) { |
|
1101 |
mpp->dst[i].pctp = 0x0000000F; |
|
1102 |
memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t)); |
|
1103 |
mpp->dst[i].raised.next = -1; |
|
1104 |
memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t)); |
|
1105 |
mpp->dst[i].servicing.next = -1; |
|
1106 |
} |
|
1107 |
/* Initialise timers */ |
|
1108 |
for (i = 0; i < MAX_TMR; i++) { |
|
1109 |
mpp->timers[i].ticc = 0x00000000; |
|
1110 |
mpp->timers[i].tibc = 0x80000000; |
|
1111 |
} |
|
1112 |
/* Go out of RESET state */ |
|
1113 |
mpp->glbc = 0x00000000; |
|
1114 |
} |
|
1115 |
|
|
1116 | 1089 |
static const MemoryRegionOps mpic_glb_ops = { |
1117 | 1090 |
.write = openpic_gbl_write, |
1118 | 1091 |
.read = openpic_gbl_read, |
... | ... | |
1185 | 1158 |
} |
1186 | 1159 |
|
1187 | 1160 |
mpp->nb_cpus = nb_cpus; |
1161 |
/* 12 external sources, 48 internal sources , 4 timer sources, |
|
1162 |
4 IPI sources, 4 messaging sources, and 8 Shared MSI sources */ |
|
1163 |
mpp->nb_irqs = 80; |
|
1164 |
mpp->vid = VID_REVISION_1_2; |
|
1165 |
mpp->veni = VENI_GENERIC; |
|
1166 |
mpp->spve_mask = 0xFFFF; |
|
1167 |
mpp->tifr_reset = 0x00000000; |
|
1168 |
mpp->ipvp_reset = 0x80000000; |
|
1169 |
mpp->ide_reset = 0x00000001; |
|
1188 | 1170 |
mpp->max_irq = MPIC_MAX_IRQ; |
1189 | 1171 |
mpp->irq_ipi0 = MPIC_IPI_IRQ; |
1190 | 1172 |
mpp->irq_tim0 = MPIC_TMR_IRQ; |
... | ... | |
1195 | 1177 |
|
1196 | 1178 |
/* Enable critical interrupt support */ |
1197 | 1179 |
mpp->flags |= OPENPIC_FLAG_IDE_CRIT; |
1198 |
mpp->reset = mpic_reset; |
|
1199 | 1180 |
|
1200 | 1181 |
register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp); |
1201 |
qemu_register_reset(mpic_reset, mpp);
|
|
1182 |
qemu_register_reset(openpic_reset, mpp);
|
|
1202 | 1183 |
|
1203 | 1184 |
return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq); |
1204 | 1185 |
} |
Also available in: Unified diff