2
0

openpic.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710
  1. /*
  2. * OpenPIC emulation
  3. *
  4. * Copyright (c) 2004 Jocelyn Mayer
  5. * 2011 Alexander Graf
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. /*
  26. *
  27. * Based on OpenPic implementations:
  28. * - Intel GW80314 I/O companion chip developer's manual
  29. * - Motorola MPC8245 & MPC8540 user manuals.
  30. * - Motorola MCP750 (aka Raven) programmer manual.
  31. * - Motorola Harrier programmer manuel
  32. *
  33. * Serial interrupts, as implemented in Raven chipset are not supported yet.
  34. *
  35. */
  36. #include "hw.h"
  37. #include "ppc_mac.h"
  38. #include "pci.h"
  39. #include "openpic.h"
  40. //#define DEBUG_OPENPIC
  41. #ifdef DEBUG_OPENPIC
  42. #define DPRINTF(fmt, ...) do { printf(fmt , ## __VA_ARGS__); } while (0)
  43. #else
  44. #define DPRINTF(fmt, ...) do { } while (0)
  45. #endif
  46. #define USE_MPCxxx /* Intel model is broken, for now */
  47. #if defined (USE_INTEL_GW80314)
  48. /* Intel GW80314 I/O Companion chip */
  49. #define MAX_CPU 4
  50. #define MAX_IRQ 32
  51. #define MAX_DBL 4
  52. #define MAX_MBX 4
  53. #define MAX_TMR 4
  54. #define VECTOR_BITS 8
  55. #define MAX_IPI 4
  56. #define VID (0x00000000)
  57. #elif defined(USE_MPCxxx)
  58. #define MAX_CPU 15
  59. #define MAX_IRQ 128
  60. #define MAX_DBL 0
  61. #define MAX_MBX 0
  62. #define MAX_TMR 4
  63. #define VECTOR_BITS 8
  64. #define MAX_IPI 4
  65. #define VID 0x03 /* MPIC version ID */
  66. #define VENI 0x00000000 /* Vendor ID */
  67. enum {
  68. IRQ_IPVP = 0,
  69. IRQ_IDE,
  70. };
  71. /* OpenPIC */
  72. #define OPENPIC_MAX_CPU 2
  73. #define OPENPIC_MAX_IRQ 64
  74. #define OPENPIC_EXT_IRQ 48
  75. #define OPENPIC_MAX_TMR MAX_TMR
  76. #define OPENPIC_MAX_IPI MAX_IPI
  77. /* Interrupt definitions */
  78. #define OPENPIC_IRQ_FE (OPENPIC_EXT_IRQ) /* Internal functional IRQ */
  79. #define OPENPIC_IRQ_ERR (OPENPIC_EXT_IRQ + 1) /* Error IRQ */
  80. #define OPENPIC_IRQ_TIM0 (OPENPIC_EXT_IRQ + 2) /* First timer IRQ */
  81. #if OPENPIC_MAX_IPI > 0
  82. #define OPENPIC_IRQ_IPI0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First IPI IRQ */
  83. #define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU * OPENPIC_MAX_IPI)) /* First doorbell IRQ */
  84. #else
  85. #define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First doorbell IRQ */
  86. #define OPENPIC_IRQ_MBX0 (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First mailbox IRQ */
  87. #endif
  88. /* MPIC */
  89. #define MPIC_MAX_CPU 1
  90. #define MPIC_MAX_EXT 12
  91. #define MPIC_MAX_INT 64
  92. #define MPIC_MAX_MSG 4
  93. #define MPIC_MAX_MSI 8
  94. #define MPIC_MAX_TMR MAX_TMR
  95. #define MPIC_MAX_IPI MAX_IPI
  96. #define MPIC_MAX_IRQ (MPIC_MAX_EXT + MPIC_MAX_INT + MPIC_MAX_TMR + MPIC_MAX_MSG + MPIC_MAX_MSI + (MPIC_MAX_IPI * MPIC_MAX_CPU))
  97. /* Interrupt definitions */
  98. #define MPIC_EXT_IRQ 0
  99. #define MPIC_INT_IRQ (MPIC_EXT_IRQ + MPIC_MAX_EXT)
  100. #define MPIC_TMR_IRQ (MPIC_INT_IRQ + MPIC_MAX_INT)
  101. #define MPIC_MSG_IRQ (MPIC_TMR_IRQ + MPIC_MAX_TMR)
  102. #define MPIC_MSI_IRQ (MPIC_MSG_IRQ + MPIC_MAX_MSG)
  103. #define MPIC_IPI_IRQ (MPIC_MSI_IRQ + MPIC_MAX_MSI)
  104. #define MPIC_GLB_REG_START 0x0
  105. #define MPIC_GLB_REG_SIZE 0x10F0
  106. #define MPIC_TMR_REG_START 0x10F0
  107. #define MPIC_TMR_REG_SIZE 0x220
  108. #define MPIC_EXT_REG_START 0x10000
  109. #define MPIC_EXT_REG_SIZE 0x180
  110. #define MPIC_INT_REG_START 0x10200
  111. #define MPIC_INT_REG_SIZE 0x800
  112. #define MPIC_MSG_REG_START 0x11600
  113. #define MPIC_MSG_REG_SIZE 0x100
  114. #define MPIC_MSI_REG_START 0x11C00
  115. #define MPIC_MSI_REG_SIZE 0x100
  116. #define MPIC_CPU_REG_START 0x20000
  117. #define MPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
  118. /*
  119. * Block Revision Register1 (BRR1): QEMU does not fully emulate
  120. * any version on MPIC. So to start with, set the IP version to 0.
  121. *
  122. * NOTE: This is Freescale MPIC specific register. Keep it here till
  123. * this code is refactored for different variants of OPENPIC and MPIC.
  124. */
  125. #define FSL_BRR1_IPID (0x0040 << 16) /* 16 bit IP-block ID */
  126. #define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */
  127. #define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */
  128. enum mpic_ide_bits {
  129. IDR_EP = 31,
  130. IDR_CI0 = 30,
  131. IDR_CI1 = 29,
  132. IDR_P1 = 1,
  133. IDR_P0 = 0,
  134. };
  135. #else
  136. #error "Please select which OpenPic implementation is to be emulated"
  137. #endif
  138. #define OPENPIC_PAGE_SIZE 4096
  139. #define BF_WIDTH(_bits_) \
  140. (((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
  141. static inline void set_bit (uint32_t *field, int bit)
  142. {
  143. field[bit >> 5] |= 1 << (bit & 0x1F);
  144. }
  145. static inline void reset_bit (uint32_t *field, int bit)
  146. {
  147. field[bit >> 5] &= ~(1 << (bit & 0x1F));
  148. }
  149. static inline int test_bit (uint32_t *field, int bit)
  150. {
  151. return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
  152. }
  153. static int get_current_cpu(void)
  154. {
  155. return cpu_single_env->cpu_index;
  156. }
  157. static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
  158. int idx);
  159. static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
  160. uint32_t val, int idx);
  161. enum {
  162. IRQ_EXTERNAL = 0x01,
  163. IRQ_INTERNAL = 0x02,
  164. IRQ_TIMER = 0x04,
  165. IRQ_SPECIAL = 0x08,
  166. };
  167. typedef struct IRQ_queue_t {
  168. uint32_t queue[BF_WIDTH(MAX_IRQ)];
  169. int next;
  170. int priority;
  171. } IRQ_queue_t;
  172. typedef struct IRQ_src_t {
  173. uint32_t ipvp; /* IRQ vector/priority register */
  174. uint32_t ide; /* IRQ destination register */
  175. int type;
  176. int last_cpu;
  177. int pending; /* TRUE if IRQ is pending */
  178. } IRQ_src_t;
  179. enum IPVP_bits {
  180. IPVP_MASK = 31,
  181. IPVP_ACTIVITY = 30,
  182. IPVP_MODE = 29,
  183. IPVP_POLARITY = 23,
  184. IPVP_SENSE = 22,
  185. };
  186. #define IPVP_PRIORITY_MASK (0x1F << 16)
  187. #define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
  188. #define IPVP_VECTOR_MASK ((1 << VECTOR_BITS) - 1)
  189. #define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK)
  190. typedef struct IRQ_dst_t {
  191. uint32_t tfrr;
  192. uint32_t pctp; /* CPU current task priority */
  193. uint32_t pcsr; /* CPU sensitivity register */
  194. IRQ_queue_t raised;
  195. IRQ_queue_t servicing;
  196. qemu_irq *irqs;
  197. } IRQ_dst_t;
  198. typedef struct openpic_t {
  199. PCIDevice pci_dev;
  200. MemoryRegion mem;
  201. /* Sub-regions */
  202. MemoryRegion sub_io_mem[7];
  203. /* Global registers */
  204. uint32_t frep; /* Feature reporting register */
  205. uint32_t glbc; /* Global configuration register */
  206. uint32_t micr; /* MPIC interrupt configuration register */
  207. uint32_t veni; /* Vendor identification register */
  208. uint32_t pint; /* Processor initialization register */
  209. uint32_t spve; /* Spurious vector register */
  210. uint32_t tifr; /* Timer frequency reporting register */
  211. /* Source registers */
  212. IRQ_src_t src[MAX_IRQ];
  213. /* Local registers per output pin */
  214. IRQ_dst_t dst[MAX_CPU];
  215. int nb_cpus;
  216. /* Timer registers */
  217. struct {
  218. uint32_t ticc; /* Global timer current count register */
  219. uint32_t tibc; /* Global timer base count register */
  220. } timers[MAX_TMR];
  221. #if MAX_DBL > 0
  222. /* Doorbell registers */
  223. uint32_t dar; /* Doorbell activate register */
  224. struct {
  225. uint32_t dmr; /* Doorbell messaging register */
  226. } doorbells[MAX_DBL];
  227. #endif
  228. #if MAX_MBX > 0
  229. /* Mailbox registers */
  230. struct {
  231. uint32_t mbr; /* Mailbox register */
  232. } mailboxes[MAX_MAILBOXES];
  233. #endif
  234. /* IRQ out is used when in bypass mode (not implemented) */
  235. qemu_irq irq_out;
  236. int max_irq;
  237. int irq_ipi0;
  238. int irq_tim0;
  239. void (*reset) (void *);
  240. void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);
  241. } openpic_t;
  242. static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
  243. {
  244. set_bit(q->queue, n_IRQ);
  245. }
  246. static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
  247. {
  248. reset_bit(q->queue, n_IRQ);
  249. }
  250. static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
  251. {
  252. return test_bit(q->queue, n_IRQ);
  253. }
  254. static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
  255. {
  256. int next, i;
  257. int priority;
  258. next = -1;
  259. priority = -1;
  260. for (i = 0; i < opp->max_irq; i++) {
  261. if (IRQ_testbit(q, i)) {
  262. DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
  263. i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
  264. if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
  265. next = i;
  266. priority = IPVP_PRIORITY(opp->src[i].ipvp);
  267. }
  268. }
  269. }
  270. q->next = next;
  271. q->priority = priority;
  272. }
  273. static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
  274. {
  275. if (q->next == -1) {
  276. /* XXX: optimize */
  277. IRQ_check(opp, q);
  278. }
  279. return q->next;
  280. }
  281. static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
  282. {
  283. IRQ_dst_t *dst;
  284. IRQ_src_t *src;
  285. int priority;
  286. dst = &opp->dst[n_CPU];
  287. src = &opp->src[n_IRQ];
  288. priority = IPVP_PRIORITY(src->ipvp);
  289. if (priority <= dst->pctp) {
  290. /* Too low priority */
  291. DPRINTF("%s: IRQ %d has too low priority on CPU %d\n",
  292. __func__, n_IRQ, n_CPU);
  293. return;
  294. }
  295. if (IRQ_testbit(&dst->raised, n_IRQ)) {
  296. /* Interrupt miss */
  297. DPRINTF("%s: IRQ %d was missed on CPU %d\n",
  298. __func__, n_IRQ, n_CPU);
  299. return;
  300. }
  301. set_bit(&src->ipvp, IPVP_ACTIVITY);
  302. IRQ_setbit(&dst->raised, n_IRQ);
  303. if (priority < dst->raised.priority) {
  304. /* An higher priority IRQ is already raised */
  305. DPRINTF("%s: IRQ %d is hidden by raised IRQ %d on CPU %d\n",
  306. __func__, n_IRQ, dst->raised.next, n_CPU);
  307. return;
  308. }
  309. IRQ_get_next(opp, &dst->raised);
  310. if (IRQ_get_next(opp, &dst->servicing) != -1 &&
  311. priority <= dst->servicing.priority) {
  312. DPRINTF("%s: IRQ %d is hidden by servicing IRQ %d on CPU %d\n",
  313. __func__, n_IRQ, dst->servicing.next, n_CPU);
  314. /* Already servicing a higher priority IRQ */
  315. return;
  316. }
  317. DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
  318. opp->irq_raise(opp, n_CPU, src);
  319. }
  320. /* update pic state because registers for n_IRQ have changed value */
  321. static void openpic_update_irq(openpic_t *opp, int n_IRQ)
  322. {
  323. IRQ_src_t *src;
  324. int i;
  325. src = &opp->src[n_IRQ];
  326. if (!src->pending) {
  327. /* no irq pending */
  328. DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
  329. return;
  330. }
  331. if (test_bit(&src->ipvp, IPVP_MASK)) {
  332. /* Interrupt source is disabled */
  333. DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
  334. return;
  335. }
  336. if (IPVP_PRIORITY(src->ipvp) == 0) {
  337. /* Priority set to zero */
  338. DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
  339. return;
  340. }
  341. if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
  342. /* IRQ already active */
  343. DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
  344. return;
  345. }
  346. if (src->ide == 0x00000000) {
  347. /* No target */
  348. DPRINTF("%s: IRQ %d has no target\n", __func__, n_IRQ);
  349. return;
  350. }
  351. if (src->ide == (1 << src->last_cpu)) {
  352. /* Only one CPU is allowed to receive this IRQ */
  353. IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
  354. } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
  355. /* Directed delivery mode */
  356. for (i = 0; i < opp->nb_cpus; i++) {
  357. if (test_bit(&src->ide, i))
  358. IRQ_local_pipe(opp, i, n_IRQ);
  359. }
  360. } else {
  361. /* Distributed delivery mode */
  362. for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
  363. if (i == opp->nb_cpus)
  364. i = 0;
  365. if (test_bit(&src->ide, i)) {
  366. IRQ_local_pipe(opp, i, n_IRQ);
  367. src->last_cpu = i;
  368. break;
  369. }
  370. }
  371. }
  372. }
  373. static void openpic_set_irq(void *opaque, int n_IRQ, int level)
  374. {
  375. openpic_t *opp = opaque;
  376. IRQ_src_t *src;
  377. src = &opp->src[n_IRQ];
  378. DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
  379. n_IRQ, level, src->ipvp);
  380. if (test_bit(&src->ipvp, IPVP_SENSE)) {
  381. /* level-sensitive irq */
  382. src->pending = level;
  383. if (!level)
  384. reset_bit(&src->ipvp, IPVP_ACTIVITY);
  385. } else {
  386. /* edge-sensitive irq */
  387. if (level)
  388. src->pending = 1;
  389. }
  390. openpic_update_irq(opp, n_IRQ);
  391. }
  392. static void openpic_reset (void *opaque)
  393. {
  394. openpic_t *opp = (openpic_t *)opaque;
  395. int i;
  396. opp->glbc = 0x80000000;
  397. /* Initialise controller registers */
  398. opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
  399. opp->veni = VENI;
  400. opp->pint = 0x00000000;
  401. opp->spve = 0x000000FF;
  402. opp->tifr = 0x003F7A00;
  403. /* ? */
  404. opp->micr = 0x00000000;
  405. /* Initialise IRQ sources */
  406. for (i = 0; i < opp->max_irq; i++) {
  407. opp->src[i].ipvp = 0xA0000000;
  408. opp->src[i].ide = 0x00000000;
  409. }
  410. /* Initialise IRQ destinations */
  411. for (i = 0; i < MAX_CPU; i++) {
  412. opp->dst[i].pctp = 0x0000000F;
  413. opp->dst[i].pcsr = 0x00000000;
  414. memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
  415. opp->dst[i].raised.next = -1;
  416. memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
  417. opp->dst[i].servicing.next = -1;
  418. }
  419. /* Initialise timers */
  420. for (i = 0; i < MAX_TMR; i++) {
  421. opp->timers[i].ticc = 0x00000000;
  422. opp->timers[i].tibc = 0x80000000;
  423. }
  424. /* Initialise doorbells */
  425. #if MAX_DBL > 0
  426. opp->dar = 0x00000000;
  427. for (i = 0; i < MAX_DBL; i++) {
  428. opp->doorbells[i].dmr = 0x00000000;
  429. }
  430. #endif
  431. /* Initialise mailboxes */
  432. #if MAX_MBX > 0
  433. for (i = 0; i < MAX_MBX; i++) { /* ? */
  434. opp->mailboxes[i].mbr = 0x00000000;
  435. }
  436. #endif
  437. /* Go out of RESET state */
  438. opp->glbc = 0x00000000;
  439. }
  440. static inline uint32_t read_IRQreg_ide(openpic_t *opp, int n_IRQ)
  441. {
  442. return opp->src[n_IRQ].ide;
  443. }
  444. static inline uint32_t read_IRQreg_ipvp(openpic_t *opp, int n_IRQ)
  445. {
  446. return opp->src[n_IRQ].ipvp;
  447. }
  448. static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val)
  449. {
  450. uint32_t tmp;
  451. tmp = val & 0xC0000000;
  452. tmp |= val & ((1ULL << MAX_CPU) - 1);
  453. opp->src[n_IRQ].ide = tmp;
  454. DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
  455. }
  456. static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val)
  457. {
  458. /* NOTE: not fully accurate for special IRQs, but simple and sufficient */
  459. /* ACTIVITY bit is read-only */
  460. opp->src[n_IRQ].ipvp = (opp->src[n_IRQ].ipvp & 0x40000000)
  461. | (val & 0x800F00FF);
  462. openpic_update_irq(opp, n_IRQ);
  463. DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n", n_IRQ, val,
  464. opp->src[n_IRQ].ipvp);
  465. }
  466. #if 0 // Code provision for Intel model
  467. #if MAX_DBL > 0
  468. static uint32_t read_doorbell_register (openpic_t *opp,
  469. int n_dbl, uint32_t offset)
  470. {
  471. uint32_t retval;
  472. switch (offset) {
  473. case DBL_IPVP_OFFSET:
  474. retval = read_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl);
  475. break;
  476. case DBL_IDE_OFFSET:
  477. retval = read_IRQreg_ide(opp, IRQ_DBL0 + n_dbl);
  478. break;
  479. case DBL_DMR_OFFSET:
  480. retval = opp->doorbells[n_dbl].dmr;
  481. break;
  482. }
  483. return retval;
  484. }
  485. static void write_doorbell_register (penpic_t *opp, int n_dbl,
  486. uint32_t offset, uint32_t value)
  487. {
  488. switch (offset) {
  489. case DBL_IVPR_OFFSET:
  490. write_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl, value);
  491. break;
  492. case DBL_IDE_OFFSET:
  493. write_IRQreg_ide(opp, IRQ_DBL0 + n_dbl, value);
  494. break;
  495. case DBL_DMR_OFFSET:
  496. opp->doorbells[n_dbl].dmr = value;
  497. break;
  498. }
  499. }
  500. #endif
  501. #if MAX_MBX > 0
  502. static uint32_t read_mailbox_register (openpic_t *opp,
  503. int n_mbx, uint32_t offset)
  504. {
  505. uint32_t retval;
  506. switch (offset) {
  507. case MBX_MBR_OFFSET:
  508. retval = opp->mailboxes[n_mbx].mbr;
  509. break;
  510. case MBX_IVPR_OFFSET:
  511. retval = read_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx);
  512. break;
  513. case MBX_DMR_OFFSET:
  514. retval = read_IRQreg_ide(opp, IRQ_MBX0 + n_mbx);
  515. break;
  516. }
  517. return retval;
  518. }
  519. static void write_mailbox_register (openpic_t *opp, int n_mbx,
  520. uint32_t address, uint32_t value)
  521. {
  522. switch (offset) {
  523. case MBX_MBR_OFFSET:
  524. opp->mailboxes[n_mbx].mbr = value;
  525. break;
  526. case MBX_IVPR_OFFSET:
  527. write_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx, value);
  528. break;
  529. case MBX_DMR_OFFSET:
  530. write_IRQreg_ide(opp, IRQ_MBX0 + n_mbx, value);
  531. break;
  532. }
  533. }
  534. #endif
  535. #endif /* 0 : Code provision for Intel model */
  536. static void openpic_gbl_write (void *opaque, target_phys_addr_t addr, uint32_t val)
  537. {
  538. openpic_t *opp = opaque;
  539. IRQ_dst_t *dst;
  540. int idx;
  541. DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
  542. if (addr & 0xF)
  543. return;
  544. switch (addr) {
  545. case 0x00: /* Block Revision Register1 (BRR1) is Readonly */
  546. break;
  547. case 0x40:
  548. case 0x50:
  549. case 0x60:
  550. case 0x70:
  551. case 0x80:
  552. case 0x90:
  553. case 0xA0:
  554. case 0xB0:
  555. openpic_cpu_write_internal(opp, addr, val, get_current_cpu());
  556. break;
  557. case 0x1000: /* FREP */
  558. break;
  559. case 0x1020: /* GLBC */
  560. if (val & 0x80000000 && opp->reset)
  561. opp->reset(opp);
  562. opp->glbc = val & ~0x80000000;
  563. break;
  564. case 0x1080: /* VENI */
  565. break;
  566. case 0x1090: /* PINT */
  567. for (idx = 0; idx < opp->nb_cpus; idx++) {
  568. if ((val & (1 << idx)) && !(opp->pint & (1 << idx))) {
  569. DPRINTF("Raise OpenPIC RESET output for CPU %d\n", idx);
  570. dst = &opp->dst[idx];
  571. qemu_irq_raise(dst->irqs[OPENPIC_OUTPUT_RESET]);
  572. } else if (!(val & (1 << idx)) && (opp->pint & (1 << idx))) {
  573. DPRINTF("Lower OpenPIC RESET output for CPU %d\n", idx);
  574. dst = &opp->dst[idx];
  575. qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_RESET]);
  576. }
  577. }
  578. opp->pint = val;
  579. break;
  580. case 0x10A0: /* IPI_IPVP */
  581. case 0x10B0:
  582. case 0x10C0:
  583. case 0x10D0:
  584. {
  585. int idx;
  586. idx = (addr - 0x10A0) >> 4;
  587. write_IRQreg_ipvp(opp, opp->irq_ipi0 + idx, val);
  588. }
  589. break;
  590. case 0x10E0: /* SPVE */
  591. opp->spve = val & 0x000000FF;
  592. break;
  593. case 0x10F0: /* TIFR */
  594. opp->tifr = val;
  595. break;
  596. default:
  597. break;
  598. }
  599. }
  600. static uint32_t openpic_gbl_read (void *opaque, target_phys_addr_t addr)
  601. {
  602. openpic_t *opp = opaque;
  603. uint32_t retval;
  604. DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
  605. retval = 0xFFFFFFFF;
  606. if (addr & 0xF)
  607. return retval;
  608. switch (addr) {
  609. case 0x1000: /* FREP */
  610. retval = opp->frep;
  611. break;
  612. case 0x1020: /* GLBC */
  613. retval = opp->glbc;
  614. break;
  615. case 0x1080: /* VENI */
  616. retval = opp->veni;
  617. break;
  618. case 0x1090: /* PINT */
  619. retval = 0x00000000;
  620. break;
  621. case 0x00: /* Block Revision Register1 (BRR1) */
  622. case 0x40:
  623. case 0x50:
  624. case 0x60:
  625. case 0x70:
  626. case 0x80:
  627. case 0x90:
  628. case 0xA0:
  629. case 0xB0:
  630. retval = openpic_cpu_read_internal(opp, addr, get_current_cpu());
  631. break;
  632. case 0x10A0: /* IPI_IPVP */
  633. case 0x10B0:
  634. case 0x10C0:
  635. case 0x10D0:
  636. {
  637. int idx;
  638. idx = (addr - 0x10A0) >> 4;
  639. retval = read_IRQreg_ipvp(opp, opp->irq_ipi0 + idx);
  640. }
  641. break;
  642. case 0x10E0: /* SPVE */
  643. retval = opp->spve;
  644. break;
  645. case 0x10F0: /* TIFR */
  646. retval = opp->tifr;
  647. break;
  648. default:
  649. break;
  650. }
  651. DPRINTF("%s: => %08x\n", __func__, retval);
  652. return retval;
  653. }
  654. static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
  655. {
  656. openpic_t *opp = opaque;
  657. int idx;
  658. DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
  659. if (addr & 0xF)
  660. return;
  661. addr -= 0x10;
  662. addr &= 0xFFFF;
  663. idx = (addr & 0xFFF0) >> 6;
  664. addr = addr & 0x30;
  665. switch (addr) {
  666. case 0x00: /* TICC */
  667. break;
  668. case 0x10: /* TIBC */
  669. if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
  670. (val & 0x80000000) == 0 &&
  671. (opp->timers[idx].tibc & 0x80000000) != 0)
  672. opp->timers[idx].ticc &= ~0x80000000;
  673. opp->timers[idx].tibc = val;
  674. break;
  675. case 0x20: /* TIVP */
  676. write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
  677. break;
  678. case 0x30: /* TIDE */
  679. write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
  680. break;
  681. }
  682. }
  683. static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
  684. {
  685. openpic_t *opp = opaque;
  686. uint32_t retval;
  687. int idx;
  688. DPRINTF("%s: addr %08x\n", __func__, addr);
  689. retval = 0xFFFFFFFF;
  690. if (addr & 0xF)
  691. return retval;
  692. addr -= 0x10;
  693. addr &= 0xFFFF;
  694. idx = (addr & 0xFFF0) >> 6;
  695. addr = addr & 0x30;
  696. switch (addr) {
  697. case 0x00: /* TICC */
  698. retval = opp->timers[idx].ticc;
  699. break;
  700. case 0x10: /* TIBC */
  701. retval = opp->timers[idx].tibc;
  702. break;
  703. case 0x20: /* TIPV */
  704. retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
  705. break;
  706. case 0x30: /* TIDE */
  707. retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
  708. break;
  709. }
  710. DPRINTF("%s: => %08x\n", __func__, retval);
  711. return retval;
  712. }
  713. static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
  714. {
  715. openpic_t *opp = opaque;
  716. int idx;
  717. DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
  718. if (addr & 0xF)
  719. return;
  720. addr = addr & 0xFFF0;
  721. idx = addr >> 5;
  722. if (addr & 0x10) {
  723. /* EXDE / IFEDE / IEEDE */
  724. write_IRQreg_ide(opp, idx, val);
  725. } else {
  726. /* EXVP / IFEVP / IEEVP */
  727. write_IRQreg_ipvp(opp, idx, val);
  728. }
  729. }
  730. static uint32_t openpic_src_read (void *opaque, uint32_t addr)
  731. {
  732. openpic_t *opp = opaque;
  733. uint32_t retval;
  734. int idx;
  735. DPRINTF("%s: addr %08x\n", __func__, addr);
  736. retval = 0xFFFFFFFF;
  737. if (addr & 0xF)
  738. return retval;
  739. addr = addr & 0xFFF0;
  740. idx = addr >> 5;
  741. if (addr & 0x10) {
  742. /* EXDE / IFEDE / IEEDE */
  743. retval = read_IRQreg_ide(opp, idx);
  744. } else {
  745. /* EXVP / IFEVP / IEEVP */
  746. retval = read_IRQreg_ipvp(opp, idx);
  747. }
  748. DPRINTF("%s: => %08x\n", __func__, retval);
  749. return retval;
  750. }
  751. static void openpic_cpu_write_internal(void *opaque, target_phys_addr_t addr,
  752. uint32_t val, int idx)
  753. {
  754. openpic_t *opp = opaque;
  755. IRQ_src_t *src;
  756. IRQ_dst_t *dst;
  757. int s_IRQ, n_IRQ;
  758. DPRINTF("%s: cpu %d addr " TARGET_FMT_plx " <= %08x\n", __func__, idx,
  759. addr, val);
  760. if (addr & 0xF)
  761. return;
  762. dst = &opp->dst[idx];
  763. addr &= 0xFF0;
  764. switch (addr) {
  765. #if MAX_IPI > 0
  766. case 0x40: /* IPIDR */
  767. case 0x50:
  768. case 0x60:
  769. case 0x70:
  770. idx = (addr - 0x40) >> 4;
  771. /* we use IDE as mask which CPUs to deliver the IPI to still. */
  772. write_IRQreg_ide(opp, opp->irq_ipi0 + idx,
  773. opp->src[opp->irq_ipi0 + idx].ide | val);
  774. openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
  775. openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
  776. break;
  777. #endif
  778. case 0x80: /* PCTP */
  779. dst->pctp = val & 0x0000000F;
  780. break;
  781. case 0x90: /* WHOAMI */
  782. /* Read-only register */
  783. break;
  784. case 0xA0: /* PIAC */
  785. /* Read-only register */
  786. break;
  787. case 0xB0: /* PEOI */
  788. DPRINTF("PEOI\n");
  789. s_IRQ = IRQ_get_next(opp, &dst->servicing);
  790. IRQ_resetbit(&dst->servicing, s_IRQ);
  791. dst->servicing.next = -1;
  792. /* Set up next servicing IRQ */
  793. s_IRQ = IRQ_get_next(opp, &dst->servicing);
  794. /* Check queued interrupts. */
  795. n_IRQ = IRQ_get_next(opp, &dst->raised);
  796. src = &opp->src[n_IRQ];
  797. if (n_IRQ != -1 &&
  798. (s_IRQ == -1 ||
  799. IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
  800. DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
  801. idx, n_IRQ);
  802. opp->irq_raise(opp, idx, src);
  803. }
  804. break;
  805. default:
  806. break;
  807. }
  808. }
  809. static void openpic_cpu_write(void *opaque, target_phys_addr_t addr, uint32_t val)
  810. {
  811. openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
  812. }
  813. static uint32_t openpic_cpu_read_internal(void *opaque, target_phys_addr_t addr,
  814. int idx)
  815. {
  816. openpic_t *opp = opaque;
  817. IRQ_src_t *src;
  818. IRQ_dst_t *dst;
  819. uint32_t retval;
  820. int n_IRQ;
  821. DPRINTF("%s: cpu %d addr " TARGET_FMT_plx "\n", __func__, idx, addr);
  822. retval = 0xFFFFFFFF;
  823. if (addr & 0xF)
  824. return retval;
  825. dst = &opp->dst[idx];
  826. addr &= 0xFF0;
  827. switch (addr) {
  828. case 0x00: /* Block Revision Register1 (BRR1) */
  829. retval = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
  830. break;
  831. case 0x80: /* PCTP */
  832. retval = dst->pctp;
  833. break;
  834. case 0x90: /* WHOAMI */
  835. retval = idx;
  836. break;
  837. case 0xA0: /* PIAC */
  838. DPRINTF("Lower OpenPIC INT output\n");
  839. qemu_irq_lower(dst->irqs[OPENPIC_OUTPUT_INT]);
  840. n_IRQ = IRQ_get_next(opp, &dst->raised);
  841. DPRINTF("PIAC: irq=%d\n", n_IRQ);
  842. if (n_IRQ == -1) {
  843. /* No more interrupt pending */
  844. retval = IPVP_VECTOR(opp->spve);
  845. } else {
  846. src = &opp->src[n_IRQ];
  847. if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
  848. !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
  849. /* - Spurious level-sensitive IRQ
  850. * - Priorities has been changed
  851. * and the pending IRQ isn't allowed anymore
  852. */
  853. reset_bit(&src->ipvp, IPVP_ACTIVITY);
  854. retval = IPVP_VECTOR(opp->spve);
  855. } else {
  856. /* IRQ enter servicing state */
  857. IRQ_setbit(&dst->servicing, n_IRQ);
  858. retval = IPVP_VECTOR(src->ipvp);
  859. }
  860. IRQ_resetbit(&dst->raised, n_IRQ);
  861. dst->raised.next = -1;
  862. if (!test_bit(&src->ipvp, IPVP_SENSE)) {
  863. /* edge-sensitive IRQ */
  864. reset_bit(&src->ipvp, IPVP_ACTIVITY);
  865. src->pending = 0;
  866. }
  867. if ((n_IRQ >= opp->irq_ipi0) && (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
  868. src->ide &= ~(1 << idx);
  869. if (src->ide && !test_bit(&src->ipvp, IPVP_SENSE)) {
  870. /* trigger on CPUs that didn't know about it yet */
  871. openpic_set_irq(opp, n_IRQ, 1);
  872. openpic_set_irq(opp, n_IRQ, 0);
  873. /* if all CPUs knew about it, set active bit again */
  874. set_bit(&src->ipvp, IPVP_ACTIVITY);
  875. }
  876. }
  877. }
  878. break;
  879. case 0xB0: /* PEOI */
  880. retval = 0;
  881. break;
  882. default:
  883. break;
  884. }
  885. DPRINTF("%s: => %08x\n", __func__, retval);
  886. return retval;
  887. }
  888. static uint32_t openpic_cpu_read(void *opaque, target_phys_addr_t addr)
  889. {
  890. return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
  891. }
  892. static void openpic_buggy_write (void *opaque,
  893. target_phys_addr_t addr, uint32_t val)
  894. {
  895. printf("Invalid OPENPIC write access !\n");
  896. }
  897. static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr)
  898. {
  899. printf("Invalid OPENPIC read access !\n");
  900. return -1;
  901. }
  902. static void openpic_writel (void *opaque,
  903. target_phys_addr_t addr, uint32_t val)
  904. {
  905. openpic_t *opp = opaque;
  906. addr &= 0x3FFFF;
  907. DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
  908. if (addr < 0x1100) {
  909. /* Global registers */
  910. openpic_gbl_write(opp, addr, val);
  911. } else if (addr < 0x10000) {
  912. /* Timers registers */
  913. openpic_timer_write(opp, addr, val);
  914. } else if (addr < 0x20000) {
  915. /* Source registers */
  916. openpic_src_write(opp, addr, val);
  917. } else {
  918. /* CPU registers */
  919. openpic_cpu_write(opp, addr, val);
  920. }
  921. }
  922. static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr)
  923. {
  924. openpic_t *opp = opaque;
  925. uint32_t retval;
  926. addr &= 0x3FFFF;
  927. DPRINTF("%s: offset %08x\n", __func__, (int)addr);
  928. if (addr < 0x1100) {
  929. /* Global registers */
  930. retval = openpic_gbl_read(opp, addr);
  931. } else if (addr < 0x10000) {
  932. /* Timers registers */
  933. retval = openpic_timer_read(opp, addr);
  934. } else if (addr < 0x20000) {
  935. /* Source registers */
  936. retval = openpic_src_read(opp, addr);
  937. } else {
  938. /* CPU registers */
  939. retval = openpic_cpu_read(opp, addr);
  940. }
  941. return retval;
  942. }
  943. static uint64_t openpic_read(void *opaque, target_phys_addr_t addr,
  944. unsigned size)
  945. {
  946. openpic_t *opp = opaque;
  947. switch (size) {
  948. case 4: return openpic_readl(opp, addr);
  949. default: return openpic_buggy_read(opp, addr);
  950. }
  951. }
  952. static void openpic_write(void *opaque, target_phys_addr_t addr,
  953. uint64_t data, unsigned size)
  954. {
  955. openpic_t *opp = opaque;
  956. switch (size) {
  957. case 4: return openpic_writel(opp, addr, data);
  958. default: return openpic_buggy_write(opp, addr, data);
  959. }
  960. }
  961. static const MemoryRegionOps openpic_ops = {
  962. .read = openpic_read,
  963. .write = openpic_write,
  964. .endianness = DEVICE_LITTLE_ENDIAN,
  965. };
  966. static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
  967. {
  968. unsigned int i;
  969. for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
  970. qemu_put_be32s(f, &q->queue[i]);
  971. qemu_put_sbe32s(f, &q->next);
  972. qemu_put_sbe32s(f, &q->priority);
  973. }
  974. static void openpic_save(QEMUFile* f, void *opaque)
  975. {
  976. openpic_t *opp = (openpic_t *)opaque;
  977. unsigned int i;
  978. qemu_put_be32s(f, &opp->frep);
  979. qemu_put_be32s(f, &opp->glbc);
  980. qemu_put_be32s(f, &opp->micr);
  981. qemu_put_be32s(f, &opp->veni);
  982. qemu_put_be32s(f, &opp->pint);
  983. qemu_put_be32s(f, &opp->spve);
  984. qemu_put_be32s(f, &opp->tifr);
  985. for (i = 0; i < opp->max_irq; i++) {
  986. qemu_put_be32s(f, &opp->src[i].ipvp);
  987. qemu_put_be32s(f, &opp->src[i].ide);
  988. qemu_put_sbe32s(f, &opp->src[i].type);
  989. qemu_put_sbe32s(f, &opp->src[i].last_cpu);
  990. qemu_put_sbe32s(f, &opp->src[i].pending);
  991. }
  992. qemu_put_sbe32s(f, &opp->nb_cpus);
  993. for (i = 0; i < opp->nb_cpus; i++) {
  994. qemu_put_be32s(f, &opp->dst[i].tfrr);
  995. qemu_put_be32s(f, &opp->dst[i].pctp);
  996. qemu_put_be32s(f, &opp->dst[i].pcsr);
  997. openpic_save_IRQ_queue(f, &opp->dst[i].raised);
  998. openpic_save_IRQ_queue(f, &opp->dst[i].servicing);
  999. }
  1000. for (i = 0; i < MAX_TMR; i++) {
  1001. qemu_put_be32s(f, &opp->timers[i].ticc);
  1002. qemu_put_be32s(f, &opp->timers[i].tibc);
  1003. }
  1004. #if MAX_DBL > 0
  1005. qemu_put_be32s(f, &opp->dar);
  1006. for (i = 0; i < MAX_DBL; i++) {
  1007. qemu_put_be32s(f, &opp->doorbells[i].dmr);
  1008. }
  1009. #endif
  1010. #if MAX_MBX > 0
  1011. for (i = 0; i < MAX_MAILBOXES; i++) {
  1012. qemu_put_be32s(f, &opp->mailboxes[i].mbr);
  1013. }
  1014. #endif
  1015. pci_device_save(&opp->pci_dev, f);
  1016. }
  1017. static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
  1018. {
  1019. unsigned int i;
  1020. for (i = 0; i < BF_WIDTH(MAX_IRQ); i++)
  1021. qemu_get_be32s(f, &q->queue[i]);
  1022. qemu_get_sbe32s(f, &q->next);
  1023. qemu_get_sbe32s(f, &q->priority);
  1024. }
  1025. static int openpic_load(QEMUFile* f, void *opaque, int version_id)
  1026. {
  1027. openpic_t *opp = (openpic_t *)opaque;
  1028. unsigned int i;
  1029. if (version_id != 1)
  1030. return -EINVAL;
  1031. qemu_get_be32s(f, &opp->frep);
  1032. qemu_get_be32s(f, &opp->glbc);
  1033. qemu_get_be32s(f, &opp->micr);
  1034. qemu_get_be32s(f, &opp->veni);
  1035. qemu_get_be32s(f, &opp->pint);
  1036. qemu_get_be32s(f, &opp->spve);
  1037. qemu_get_be32s(f, &opp->tifr);
  1038. for (i = 0; i < opp->max_irq; i++) {
  1039. qemu_get_be32s(f, &opp->src[i].ipvp);
  1040. qemu_get_be32s(f, &opp->src[i].ide);
  1041. qemu_get_sbe32s(f, &opp->src[i].type);
  1042. qemu_get_sbe32s(f, &opp->src[i].last_cpu);
  1043. qemu_get_sbe32s(f, &opp->src[i].pending);
  1044. }
  1045. qemu_get_sbe32s(f, &opp->nb_cpus);
  1046. for (i = 0; i < opp->nb_cpus; i++) {
  1047. qemu_get_be32s(f, &opp->dst[i].tfrr);
  1048. qemu_get_be32s(f, &opp->dst[i].pctp);
  1049. qemu_get_be32s(f, &opp->dst[i].pcsr);
  1050. openpic_load_IRQ_queue(f, &opp->dst[i].raised);
  1051. openpic_load_IRQ_queue(f, &opp->dst[i].servicing);
  1052. }
  1053. for (i = 0; i < MAX_TMR; i++) {
  1054. qemu_get_be32s(f, &opp->timers[i].ticc);
  1055. qemu_get_be32s(f, &opp->timers[i].tibc);
  1056. }
  1057. #if MAX_DBL > 0
  1058. qemu_get_be32s(f, &opp->dar);
  1059. for (i = 0; i < MAX_DBL; i++) {
  1060. qemu_get_be32s(f, &opp->doorbells[i].dmr);
  1061. }
  1062. #endif
  1063. #if MAX_MBX > 0
  1064. for (i = 0; i < MAX_MAILBOXES; i++) {
  1065. qemu_get_be32s(f, &opp->mailboxes[i].mbr);
  1066. }
  1067. #endif
  1068. return pci_device_load(&opp->pci_dev, f);
  1069. }
  1070. static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
  1071. {
  1072. qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
  1073. }
  1074. qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
  1075. qemu_irq **irqs, qemu_irq irq_out)
  1076. {
  1077. openpic_t *opp;
  1078. int i, m;
  1079. /* XXX: for now, only one CPU is supported */
  1080. if (nb_cpus != 1)
  1081. return NULL;
  1082. opp = g_malloc0(sizeof(openpic_t));
  1083. memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
  1084. // isu_base &= 0xFFFC0000;
  1085. opp->nb_cpus = nb_cpus;
  1086. opp->max_irq = OPENPIC_MAX_IRQ;
  1087. opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
  1088. opp->irq_tim0 = OPENPIC_IRQ_TIM0;
  1089. /* Set IRQ types */
  1090. for (i = 0; i < OPENPIC_EXT_IRQ; i++) {
  1091. opp->src[i].type = IRQ_EXTERNAL;
  1092. }
  1093. for (; i < OPENPIC_IRQ_TIM0; i++) {
  1094. opp->src[i].type = IRQ_SPECIAL;
  1095. }
  1096. #if MAX_IPI > 0
  1097. m = OPENPIC_IRQ_IPI0;
  1098. #else
  1099. m = OPENPIC_IRQ_DBL0;
  1100. #endif
  1101. for (; i < m; i++) {
  1102. opp->src[i].type = IRQ_TIMER;
  1103. }
  1104. for (; i < OPENPIC_MAX_IRQ; i++) {
  1105. opp->src[i].type = IRQ_INTERNAL;
  1106. }
  1107. for (i = 0; i < nb_cpus; i++)
  1108. opp->dst[i].irqs = irqs[i];
  1109. opp->irq_out = irq_out;
  1110. register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
  1111. openpic_save, openpic_load, opp);
  1112. qemu_register_reset(openpic_reset, opp);
  1113. opp->irq_raise = openpic_irq_raise;
  1114. opp->reset = openpic_reset;
  1115. if (pmem)
  1116. *pmem = &opp->mem;
  1117. return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
  1118. }
  1119. static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
  1120. {
  1121. int n_ci = IDR_CI0 - n_CPU;
  1122. if(test_bit(&src->ide, n_ci)) {
  1123. qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
  1124. }
  1125. else {
  1126. qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
  1127. }
  1128. }
  1129. static void mpic_reset (void *opaque)
  1130. {
  1131. openpic_t *mpp = (openpic_t *)opaque;
  1132. int i;
  1133. mpp->glbc = 0x80000000;
  1134. /* Initialise controller registers */
  1135. mpp->frep = 0x004f0002 | ((mpp->nb_cpus - 1) << 8);
  1136. mpp->veni = VENI;
  1137. mpp->pint = 0x00000000;
  1138. mpp->spve = 0x0000FFFF;
  1139. /* Initialise IRQ sources */
  1140. for (i = 0; i < mpp->max_irq; i++) {
  1141. mpp->src[i].ipvp = 0x80800000;
  1142. mpp->src[i].ide = 0x00000001;
  1143. }
  1144. /* Set IDE for IPIs to 0 so we don't get spurious interrupts */
  1145. for (i = mpp->irq_ipi0; i < (mpp->irq_ipi0 + MAX_IPI); i++) {
  1146. mpp->src[i].ide = 0;
  1147. }
  1148. /* Initialise IRQ destinations */
  1149. for (i = 0; i < MAX_CPU; i++) {
  1150. mpp->dst[i].pctp = 0x0000000F;
  1151. mpp->dst[i].tfrr = 0x00000000;
  1152. memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
  1153. mpp->dst[i].raised.next = -1;
  1154. memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
  1155. mpp->dst[i].servicing.next = -1;
  1156. }
  1157. /* Initialise timers */
  1158. for (i = 0; i < MAX_TMR; i++) {
  1159. mpp->timers[i].ticc = 0x00000000;
  1160. mpp->timers[i].tibc = 0x80000000;
  1161. }
  1162. /* Go out of RESET state */
  1163. mpp->glbc = 0x00000000;
  1164. }
  1165. static void mpic_timer_write (void *opaque, target_phys_addr_t addr, uint32_t val)
  1166. {
  1167. openpic_t *mpp = opaque;
  1168. int idx, cpu;
  1169. DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
  1170. if (addr & 0xF)
  1171. return;
  1172. addr &= 0xFFFF;
  1173. cpu = addr >> 12;
  1174. idx = (addr >> 6) & 0x3;
  1175. switch (addr & 0x30) {
  1176. case 0x00: /* gtccr */
  1177. break;
  1178. case 0x10: /* gtbcr */
  1179. if ((mpp->timers[idx].ticc & 0x80000000) != 0 &&
  1180. (val & 0x80000000) == 0 &&
  1181. (mpp->timers[idx].tibc & 0x80000000) != 0)
  1182. mpp->timers[idx].ticc &= ~0x80000000;
  1183. mpp->timers[idx].tibc = val;
  1184. break;
  1185. case 0x20: /* GTIVPR */
  1186. write_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx, val);
  1187. break;
  1188. case 0x30: /* GTIDR & TFRR */
  1189. if ((addr & 0xF0) == 0xF0)
  1190. mpp->dst[cpu].tfrr = val;
  1191. else
  1192. write_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx, val);
  1193. break;
  1194. }
  1195. }
  1196. static uint32_t mpic_timer_read (void *opaque, target_phys_addr_t addr)
  1197. {
  1198. openpic_t *mpp = opaque;
  1199. uint32_t retval;
  1200. int idx, cpu;
  1201. DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
  1202. retval = 0xFFFFFFFF;
  1203. if (addr & 0xF)
  1204. return retval;
  1205. addr &= 0xFFFF;
  1206. cpu = addr >> 12;
  1207. idx = (addr >> 6) & 0x3;
  1208. switch (addr & 0x30) {
  1209. case 0x00: /* gtccr */
  1210. retval = mpp->timers[idx].ticc;
  1211. break;
  1212. case 0x10: /* gtbcr */
  1213. retval = mpp->timers[idx].tibc;
  1214. break;
  1215. case 0x20: /* TIPV */
  1216. retval = read_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx);
  1217. break;
  1218. case 0x30: /* TIDR */
  1219. if ((addr &0xF0) == 0XF0)
  1220. retval = mpp->dst[cpu].tfrr;
  1221. else
  1222. retval = read_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx);
  1223. break;
  1224. }
  1225. DPRINTF("%s: => %08x\n", __func__, retval);
  1226. return retval;
  1227. }
  1228. static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr,
  1229. uint32_t val)
  1230. {
  1231. openpic_t *mpp = opaque;
  1232. int idx = MPIC_EXT_IRQ;
  1233. DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
  1234. if (addr & 0xF)
  1235. return;
  1236. if (addr < MPIC_EXT_REG_SIZE) {
  1237. idx += (addr & 0xFFF0) >> 5;
  1238. if (addr & 0x10) {
  1239. /* EXDE / IFEDE / IEEDE */
  1240. write_IRQreg_ide(mpp, idx, val);
  1241. } else {
  1242. /* EXVP / IFEVP / IEEVP */
  1243. write_IRQreg_ipvp(mpp, idx, val);
  1244. }
  1245. }
  1246. }
  1247. static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr)
  1248. {
  1249. openpic_t *mpp = opaque;
  1250. uint32_t retval;
  1251. int idx = MPIC_EXT_IRQ;
  1252. DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
  1253. retval = 0xFFFFFFFF;
  1254. if (addr & 0xF)
  1255. return retval;
  1256. if (addr < MPIC_EXT_REG_SIZE) {
  1257. idx += (addr & 0xFFF0) >> 5;
  1258. if (addr & 0x10) {
  1259. /* EXDE / IFEDE / IEEDE */
  1260. retval = read_IRQreg_ide(mpp, idx);
  1261. } else {
  1262. /* EXVP / IFEVP / IEEVP */
  1263. retval = read_IRQreg_ipvp(mpp, idx);
  1264. }
  1265. DPRINTF("%s: => %08x\n", __func__, retval);
  1266. }
  1267. return retval;
  1268. }
  1269. static void mpic_src_int_write (void *opaque, target_phys_addr_t addr,
  1270. uint32_t val)
  1271. {
  1272. openpic_t *mpp = opaque;
  1273. int idx = MPIC_INT_IRQ;
  1274. DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
  1275. if (addr & 0xF)
  1276. return;
  1277. if (addr < MPIC_INT_REG_SIZE) {
  1278. idx += (addr & 0xFFF0) >> 5;
  1279. if (addr & 0x10) {
  1280. /* EXDE / IFEDE / IEEDE */
  1281. write_IRQreg_ide(mpp, idx, val);
  1282. } else {
  1283. /* EXVP / IFEVP / IEEVP */
  1284. write_IRQreg_ipvp(mpp, idx, val);
  1285. }
  1286. }
  1287. }
  1288. static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr)
  1289. {
  1290. openpic_t *mpp = opaque;
  1291. uint32_t retval;
  1292. int idx = MPIC_INT_IRQ;
  1293. DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
  1294. retval = 0xFFFFFFFF;
  1295. if (addr & 0xF)
  1296. return retval;
  1297. if (addr < MPIC_INT_REG_SIZE) {
  1298. idx += (addr & 0xFFF0) >> 5;
  1299. if (addr & 0x10) {
  1300. /* EXDE / IFEDE / IEEDE */
  1301. retval = read_IRQreg_ide(mpp, idx);
  1302. } else {
  1303. /* EXVP / IFEVP / IEEVP */
  1304. retval = read_IRQreg_ipvp(mpp, idx);
  1305. }
  1306. DPRINTF("%s: => %08x\n", __func__, retval);
  1307. }
  1308. return retval;
  1309. }
  1310. static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr,
  1311. uint32_t val)
  1312. {
  1313. openpic_t *mpp = opaque;
  1314. int idx = MPIC_MSG_IRQ;
  1315. DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
  1316. if (addr & 0xF)
  1317. return;
  1318. if (addr < MPIC_MSG_REG_SIZE) {
  1319. idx += (addr & 0xFFF0) >> 5;
  1320. if (addr & 0x10) {
  1321. /* EXDE / IFEDE / IEEDE */
  1322. write_IRQreg_ide(mpp, idx, val);
  1323. } else {
  1324. /* EXVP / IFEVP / IEEVP */
  1325. write_IRQreg_ipvp(mpp, idx, val);
  1326. }
  1327. }
  1328. }
  1329. static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr)
  1330. {
  1331. openpic_t *mpp = opaque;
  1332. uint32_t retval;
  1333. int idx = MPIC_MSG_IRQ;
  1334. DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
  1335. retval = 0xFFFFFFFF;
  1336. if (addr & 0xF)
  1337. return retval;
  1338. if (addr < MPIC_MSG_REG_SIZE) {
  1339. idx += (addr & 0xFFF0) >> 5;
  1340. if (addr & 0x10) {
  1341. /* EXDE / IFEDE / IEEDE */
  1342. retval = read_IRQreg_ide(mpp, idx);
  1343. } else {
  1344. /* EXVP / IFEVP / IEEVP */
  1345. retval = read_IRQreg_ipvp(mpp, idx);
  1346. }
  1347. DPRINTF("%s: => %08x\n", __func__, retval);
  1348. }
  1349. return retval;
  1350. }
  1351. static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr,
  1352. uint32_t val)
  1353. {
  1354. openpic_t *mpp = opaque;
  1355. int idx = MPIC_MSI_IRQ;
  1356. DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
  1357. if (addr & 0xF)
  1358. return;
  1359. if (addr < MPIC_MSI_REG_SIZE) {
  1360. idx += (addr & 0xFFF0) >> 5;
  1361. if (addr & 0x10) {
  1362. /* EXDE / IFEDE / IEEDE */
  1363. write_IRQreg_ide(mpp, idx, val);
  1364. } else {
  1365. /* EXVP / IFEVP / IEEVP */
  1366. write_IRQreg_ipvp(mpp, idx, val);
  1367. }
  1368. }
  1369. }
  1370. static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr)
  1371. {
  1372. openpic_t *mpp = opaque;
  1373. uint32_t retval;
  1374. int idx = MPIC_MSI_IRQ;
  1375. DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
  1376. retval = 0xFFFFFFFF;
  1377. if (addr & 0xF)
  1378. return retval;
  1379. if (addr < MPIC_MSI_REG_SIZE) {
  1380. idx += (addr & 0xFFF0) >> 5;
  1381. if (addr & 0x10) {
  1382. /* EXDE / IFEDE / IEEDE */
  1383. retval = read_IRQreg_ide(mpp, idx);
  1384. } else {
  1385. /* EXVP / IFEVP / IEEVP */
  1386. retval = read_IRQreg_ipvp(mpp, idx);
  1387. }
  1388. DPRINTF("%s: => %08x\n", __func__, retval);
  1389. }
  1390. return retval;
  1391. }
  1392. static const MemoryRegionOps mpic_glb_ops = {
  1393. .old_mmio = {
  1394. .write = { openpic_buggy_write,
  1395. openpic_buggy_write,
  1396. openpic_gbl_write,
  1397. },
  1398. .read = { openpic_buggy_read,
  1399. openpic_buggy_read,
  1400. openpic_gbl_read,
  1401. },
  1402. },
  1403. .endianness = DEVICE_BIG_ENDIAN,
  1404. };
  1405. static const MemoryRegionOps mpic_tmr_ops = {
  1406. .old_mmio = {
  1407. .write = { openpic_buggy_write,
  1408. openpic_buggy_write,
  1409. mpic_timer_write,
  1410. },
  1411. .read = { openpic_buggy_read,
  1412. openpic_buggy_read,
  1413. mpic_timer_read,
  1414. },
  1415. },
  1416. .endianness = DEVICE_BIG_ENDIAN,
  1417. };
  1418. static const MemoryRegionOps mpic_cpu_ops = {
  1419. .old_mmio = {
  1420. .write = { openpic_buggy_write,
  1421. openpic_buggy_write,
  1422. openpic_cpu_write,
  1423. },
  1424. .read = { openpic_buggy_read,
  1425. openpic_buggy_read,
  1426. openpic_cpu_read,
  1427. },
  1428. },
  1429. .endianness = DEVICE_BIG_ENDIAN,
  1430. };
  1431. static const MemoryRegionOps mpic_ext_ops = {
  1432. .old_mmio = {
  1433. .write = { openpic_buggy_write,
  1434. openpic_buggy_write,
  1435. mpic_src_ext_write,
  1436. },
  1437. .read = { openpic_buggy_read,
  1438. openpic_buggy_read,
  1439. mpic_src_ext_read,
  1440. },
  1441. },
  1442. .endianness = DEVICE_BIG_ENDIAN,
  1443. };
  1444. static const MemoryRegionOps mpic_int_ops = {
  1445. .old_mmio = {
  1446. .write = { openpic_buggy_write,
  1447. openpic_buggy_write,
  1448. mpic_src_int_write,
  1449. },
  1450. .read = { openpic_buggy_read,
  1451. openpic_buggy_read,
  1452. mpic_src_int_read,
  1453. },
  1454. },
  1455. .endianness = DEVICE_BIG_ENDIAN,
  1456. };
  1457. static const MemoryRegionOps mpic_msg_ops = {
  1458. .old_mmio = {
  1459. .write = { openpic_buggy_write,
  1460. openpic_buggy_write,
  1461. mpic_src_msg_write,
  1462. },
  1463. .read = { openpic_buggy_read,
  1464. openpic_buggy_read,
  1465. mpic_src_msg_read,
  1466. },
  1467. },
  1468. .endianness = DEVICE_BIG_ENDIAN,
  1469. };
  1470. static const MemoryRegionOps mpic_msi_ops = {
  1471. .old_mmio = {
  1472. .write = { openpic_buggy_write,
  1473. openpic_buggy_write,
  1474. mpic_src_msi_write,
  1475. },
  1476. .read = { openpic_buggy_read,
  1477. openpic_buggy_read,
  1478. mpic_src_msi_read,
  1479. },
  1480. },
  1481. .endianness = DEVICE_BIG_ENDIAN,
  1482. };
  1483. qemu_irq *mpic_init (MemoryRegion *address_space, target_phys_addr_t base,
  1484. int nb_cpus, qemu_irq **irqs, qemu_irq irq_out)
  1485. {
  1486. openpic_t *mpp;
  1487. int i;
  1488. struct {
  1489. const char *name;
  1490. MemoryRegionOps const *ops;
  1491. target_phys_addr_t start_addr;
  1492. ram_addr_t size;
  1493. } const list[] = {
  1494. {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
  1495. {"tmr", &mpic_tmr_ops, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
  1496. {"ext", &mpic_ext_ops, MPIC_EXT_REG_START, MPIC_EXT_REG_SIZE},
  1497. {"int", &mpic_int_ops, MPIC_INT_REG_START, MPIC_INT_REG_SIZE},
  1498. {"msg", &mpic_msg_ops, MPIC_MSG_REG_START, MPIC_MSG_REG_SIZE},
  1499. {"msi", &mpic_msi_ops, MPIC_MSI_REG_START, MPIC_MSI_REG_SIZE},
  1500. {"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
  1501. };
  1502. mpp = g_malloc0(sizeof(openpic_t));
  1503. memory_region_init(&mpp->mem, "mpic", 0x40000);
  1504. memory_region_add_subregion(address_space, base, &mpp->mem);
  1505. for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
  1506. memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp,
  1507. list[i].name, list[i].size);
  1508. memory_region_add_subregion(&mpp->mem, list[i].start_addr,
  1509. &mpp->sub_io_mem[i]);
  1510. }
  1511. mpp->nb_cpus = nb_cpus;
  1512. mpp->max_irq = MPIC_MAX_IRQ;
  1513. mpp->irq_ipi0 = MPIC_IPI_IRQ;
  1514. mpp->irq_tim0 = MPIC_TMR_IRQ;
  1515. for (i = 0; i < nb_cpus; i++)
  1516. mpp->dst[i].irqs = irqs[i];
  1517. mpp->irq_out = irq_out;
  1518. mpp->irq_raise = mpic_irq_raise;
  1519. mpp->reset = mpic_reset;
  1520. register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
  1521. qemu_register_reset(mpic_reset, mpp);
  1522. return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
  1523. }