xref: /openbmc/qemu/hw/misc/iotkit-secctl.c (revision 28ae3179fc52d2e4d870b635c4a412aab99759e7)
1  /*
2   * Arm IoT Kit security controller
3   *
4   * Copyright (c) 2018 Linaro Limited
5   * Written by Peter Maydell
6   *
7   * This program is free software; you can redistribute it and/or modify
8   * it under the terms of the GNU General Public License version 2 or
9   * (at your option) any later version.
10   */
11  
12  #include "qemu/osdep.h"
13  #include "qemu/log.h"
14  #include "qemu/module.h"
15  #include "qapi/error.h"
16  #include "trace.h"
17  #include "hw/sysbus.h"
18  #include "migration/vmstate.h"
19  #include "hw/registerfields.h"
20  #include "hw/irq.h"
21  #include "hw/misc/iotkit-secctl.h"
22  #include "hw/arm/armsse-version.h"
23  #include "hw/qdev-properties.h"
24  
25  /* Registers in the secure privilege control block */
26  REG32(SECRESPCFG, 0x10)
27  REG32(NSCCFG, 0x14)
28  REG32(SECMPCINTSTATUS, 0x1c)
29  REG32(SECPPCINTSTAT, 0x20)
30  REG32(SECPPCINTCLR, 0x24)
31  REG32(SECPPCINTEN, 0x28)
32  REG32(SECMSCINTSTAT, 0x30)
33  REG32(SECMSCINTCLR, 0x34)
34  REG32(SECMSCINTEN, 0x38)
35  REG32(BRGINTSTAT, 0x40)
36  REG32(BRGINTCLR, 0x44)
37  REG32(BRGINTEN, 0x48)
38  REG32(AHBNSPPC0, 0x50)
39  REG32(AHBNSPPCEXP0, 0x60)
40  REG32(AHBNSPPCEXP1, 0x64)
41  REG32(AHBNSPPCEXP2, 0x68)
42  REG32(AHBNSPPCEXP3, 0x6c)
43  REG32(APBNSPPC0, 0x70)
44  REG32(APBNSPPC1, 0x74)
45  REG32(APBNSPPCEXP0, 0x80)
46  REG32(APBNSPPCEXP1, 0x84)
47  REG32(APBNSPPCEXP2, 0x88)
48  REG32(APBNSPPCEXP3, 0x8c)
49  REG32(AHBSPPPC0, 0x90)
50  REG32(AHBSPPPCEXP0, 0xa0)
51  REG32(AHBSPPPCEXP1, 0xa4)
52  REG32(AHBSPPPCEXP2, 0xa8)
53  REG32(AHBSPPPCEXP3, 0xac)
54  REG32(APBSPPPC0, 0xb0)
55  REG32(APBSPPPC1, 0xb4)
56  REG32(APBSPPPCEXP0, 0xc0)
57  REG32(APBSPPPCEXP1, 0xc4)
58  REG32(APBSPPPCEXP2, 0xc8)
59  REG32(APBSPPPCEXP3, 0xcc)
60  REG32(NSMSCEXP, 0xd0)
61  REG32(PID4, 0xfd0)
62  REG32(PID5, 0xfd4)
63  REG32(PID6, 0xfd8)
64  REG32(PID7, 0xfdc)
65  REG32(PID0, 0xfe0)
66  REG32(PID1, 0xfe4)
67  REG32(PID2, 0xfe8)
68  REG32(PID3, 0xfec)
69  REG32(CID0, 0xff0)
70  REG32(CID1, 0xff4)
71  REG32(CID2, 0xff8)
72  REG32(CID3, 0xffc)
73  
74  /* Registers in the non-secure privilege control block */
75  REG32(AHBNSPPPC0, 0x90)
76  REG32(AHBNSPPPCEXP0, 0xa0)
77  REG32(AHBNSPPPCEXP1, 0xa4)
78  REG32(AHBNSPPPCEXP2, 0xa8)
79  REG32(AHBNSPPPCEXP3, 0xac)
80  REG32(APBNSPPPC0, 0xb0)
81  REG32(APBNSPPPC1, 0xb4)
82  REG32(APBNSPPPCEXP0, 0xc0)
83  REG32(APBNSPPPCEXP1, 0xc4)
84  REG32(APBNSPPPCEXP2, 0xc8)
85  REG32(APBNSPPPCEXP3, 0xcc)
86  /* PID and CID registers are also present in the NS block */
87  
88  static const uint8_t iotkit_secctl_s_idregs[] = {
89      0x04, 0x00, 0x00, 0x00,
90      0x52, 0xb8, 0x0b, 0x00,
91      0x0d, 0xf0, 0x05, 0xb1,
92  };
93  
94  static const uint8_t iotkit_secctl_ns_idregs[] = {
95      0x04, 0x00, 0x00, 0x00,
96      0x53, 0xb8, 0x0b, 0x00,
97      0x0d, 0xf0, 0x05, 0xb1,
98  };
99  
100  static const uint8_t iotkit_secctl_s_sse300_idregs[] = {
101      0x04, 0x00, 0x00, 0x00,
102      0x52, 0xb8, 0x2b, 0x00,
103      0x0d, 0xf0, 0x05, 0xb1,
104  };
105  
106  static const uint8_t iotkit_secctl_ns_sse300_idregs[] = {
107      0x04, 0x00, 0x00, 0x00,
108      0x53, 0xb8, 0x2b, 0x00,
109      0x0d, 0xf0, 0x05, 0xb1,
110  };
111  
112  
113  /* The register sets for the various PPCs (AHB internal, APB internal,
114   * AHB expansion, APB expansion) are all set up so that they are
115   * in 16-aligned blocks so offsets 0xN0, 0xN4, 0xN8, 0xNC are PPCs
116   * 0, 1, 2, 3 of that type, so we can convert a register address offset
117   * into an index into a PPC array easily.
118   */
offset_to_ppc_idx(uint32_t offset)119  static inline int offset_to_ppc_idx(uint32_t offset)
120  {
121      return extract32(offset, 2, 2);
122  }
123  
124  typedef void PerPPCFunction(IoTKitSecCtlPPC *ppc);
125  
foreach_ppc(IoTKitSecCtl * s,PerPPCFunction * fn)126  static void foreach_ppc(IoTKitSecCtl *s, PerPPCFunction *fn)
127  {
128      int i;
129  
130      for (i = 0; i < IOTS_NUM_APB_PPC; i++) {
131          fn(&s->apb[i]);
132      }
133      for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
134          fn(&s->apbexp[i]);
135      }
136      for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
137          fn(&s->ahbexp[i]);
138      }
139  }
140  
iotkit_secctl_s_read(void * opaque,hwaddr addr,uint64_t * pdata,unsigned size,MemTxAttrs attrs)141  static MemTxResult iotkit_secctl_s_read(void *opaque, hwaddr addr,
142                                          uint64_t *pdata,
143                                          unsigned size, MemTxAttrs attrs)
144  {
145      uint64_t r;
146      uint32_t offset = addr & ~0x3;
147      IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
148  
149      switch (offset) {
150      case A_AHBNSPPC0:
151      case A_AHBSPPPC0:
152          r = 0;
153          break;
154      case A_SECRESPCFG:
155          r = s->secrespcfg;
156          break;
157      case A_NSCCFG:
158          r = s->nsccfg;
159          break;
160      case A_SECMPCINTSTATUS:
161          r = s->mpcintstatus;
162          break;
163      case A_SECPPCINTSTAT:
164          r = s->secppcintstat;
165          break;
166      case A_SECPPCINTEN:
167          r = s->secppcinten;
168          break;
169      case A_BRGINTSTAT:
170          /* QEMU's bus fabric can never report errors as it doesn't buffer
171           * writes, so we never report bridge interrupts.
172           */
173          r = 0;
174          break;
175      case A_BRGINTEN:
176          r = s->brginten;
177          break;
178      case A_AHBNSPPCEXP0:
179      case A_AHBNSPPCEXP1:
180      case A_AHBNSPPCEXP2:
181      case A_AHBNSPPCEXP3:
182          r = s->ahbexp[offset_to_ppc_idx(offset)].ns;
183          break;
184      case A_APBNSPPC0:
185      case A_APBNSPPC1:
186          r = s->apb[offset_to_ppc_idx(offset)].ns;
187          break;
188      case A_APBNSPPCEXP0:
189      case A_APBNSPPCEXP1:
190      case A_APBNSPPCEXP2:
191      case A_APBNSPPCEXP3:
192          r = s->apbexp[offset_to_ppc_idx(offset)].ns;
193          break;
194      case A_AHBSPPPCEXP0:
195      case A_AHBSPPPCEXP1:
196      case A_AHBSPPPCEXP2:
197      case A_AHBSPPPCEXP3:
198          r = s->apbexp[offset_to_ppc_idx(offset)].sp;
199          break;
200      case A_APBSPPPC0:
201      case A_APBSPPPC1:
202          r = s->apb[offset_to_ppc_idx(offset)].sp;
203          break;
204      case A_APBSPPPCEXP0:
205      case A_APBSPPPCEXP1:
206      case A_APBSPPPCEXP2:
207      case A_APBSPPPCEXP3:
208          r = s->apbexp[offset_to_ppc_idx(offset)].sp;
209          break;
210      case A_SECMSCINTSTAT:
211          r = s->secmscintstat;
212          break;
213      case A_SECMSCINTEN:
214          r = s->secmscinten;
215          break;
216      case A_NSMSCEXP:
217          r = s->nsmscexp;
218          break;
219      case A_PID4:
220      case A_PID5:
221      case A_PID6:
222      case A_PID7:
223      case A_PID0:
224      case A_PID1:
225      case A_PID2:
226      case A_PID3:
227      case A_CID0:
228      case A_CID1:
229      case A_CID2:
230      case A_CID3:
231          switch (s->sse_version) {
232          case ARMSSE_SSE300:
233              r = iotkit_secctl_s_sse300_idregs[(offset - A_PID4) / 4];
234              break;
235          default:
236              r = iotkit_secctl_s_idregs[(offset - A_PID4) / 4];
237              break;
238          }
239          break;
240      case A_SECPPCINTCLR:
241      case A_SECMSCINTCLR:
242      case A_BRGINTCLR:
243          qemu_log_mask(LOG_GUEST_ERROR,
244                        "IotKit SecCtl S block read: write-only offset 0x%x\n",
245                        offset);
246          r = 0;
247          break;
248      default:
249          qemu_log_mask(LOG_GUEST_ERROR,
250                        "IotKit SecCtl S block read: bad offset 0x%x\n", offset);
251          r = 0;
252          break;
253      }
254  
255      if (size != 4) {
256          /* None of our registers are access-sensitive, so just pull the right
257           * byte out of the word read result.
258           */
259          r = extract32(r, (addr & 3) * 8, size * 8);
260      }
261  
262      trace_iotkit_secctl_s_read(offset, r, size);
263      *pdata = r;
264      return MEMTX_OK;
265  }
266  
iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC * ppc)267  static void iotkit_secctl_update_ppc_ap(IoTKitSecCtlPPC *ppc)
268  {
269      int i;
270  
271      for (i = 0; i < ppc->numports; i++) {
272          bool v;
273  
274          if (extract32(ppc->ns, i, 1)) {
275              v = extract32(ppc->nsp, i, 1);
276          } else {
277              v = extract32(ppc->sp, i, 1);
278          }
279          qemu_set_irq(ppc->ap[i], v);
280      }
281  }
282  
iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC * ppc,uint32_t value)283  static void iotkit_secctl_ppc_ns_write(IoTKitSecCtlPPC *ppc, uint32_t value)
284  {
285      int i;
286  
287      ppc->ns = value & MAKE_64BIT_MASK(0, ppc->numports);
288      for (i = 0; i < ppc->numports; i++) {
289          qemu_set_irq(ppc->nonsec[i], extract32(ppc->ns, i, 1));
290      }
291      iotkit_secctl_update_ppc_ap(ppc);
292  }
293  
iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC * ppc,uint32_t value)294  static void iotkit_secctl_ppc_sp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
295  {
296      ppc->sp = value & MAKE_64BIT_MASK(0, ppc->numports);
297      iotkit_secctl_update_ppc_ap(ppc);
298  }
299  
iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC * ppc,uint32_t value)300  static void iotkit_secctl_ppc_nsp_write(IoTKitSecCtlPPC *ppc, uint32_t value)
301  {
302      ppc->nsp = value & MAKE_64BIT_MASK(0, ppc->numports);
303      iotkit_secctl_update_ppc_ap(ppc);
304  }
305  
iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC * ppc)306  static void iotkit_secctl_ppc_update_irq_clear(IoTKitSecCtlPPC *ppc)
307  {
308      uint32_t value = ppc->parent->secppcintstat;
309  
310      qemu_set_irq(ppc->irq_clear, extract32(value, ppc->irq_bit_offset, 1));
311  }
312  
iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC * ppc)313  static void iotkit_secctl_ppc_update_irq_enable(IoTKitSecCtlPPC *ppc)
314  {
315      uint32_t value = ppc->parent->secppcinten;
316  
317      qemu_set_irq(ppc->irq_enable, extract32(value, ppc->irq_bit_offset, 1));
318  }
319  
iotkit_secctl_update_mscexp_irqs(qemu_irq * msc_irqs,uint32_t value)320  static void iotkit_secctl_update_mscexp_irqs(qemu_irq *msc_irqs, uint32_t value)
321  {
322      int i;
323  
324      for (i = 0; i < IOTS_NUM_EXP_MSC; i++) {
325          qemu_set_irq(msc_irqs[i], extract32(value, i + 16, 1));
326      }
327  }
328  
iotkit_secctl_update_msc_irq(IoTKitSecCtl * s)329  static void iotkit_secctl_update_msc_irq(IoTKitSecCtl *s)
330  {
331      /* Update the combined MSC IRQ, based on S_MSCEXP_STATUS and S_MSCEXP_EN */
332      bool level = s->secmscintstat & s->secmscinten;
333  
334      qemu_set_irq(s->msc_irq, level);
335  }
336  
iotkit_secctl_s_write(void * opaque,hwaddr addr,uint64_t value,unsigned size,MemTxAttrs attrs)337  static MemTxResult iotkit_secctl_s_write(void *opaque, hwaddr addr,
338                                           uint64_t value,
339                                           unsigned size, MemTxAttrs attrs)
340  {
341      IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
342      uint32_t offset = addr;
343      IoTKitSecCtlPPC *ppc;
344  
345      trace_iotkit_secctl_s_write(offset, value, size);
346  
347      if (size != 4) {
348          /* Byte and halfword writes are ignored */
349          qemu_log_mask(LOG_GUEST_ERROR,
350                        "IotKit SecCtl S block write: bad size, ignored\n");
351          return MEMTX_OK;
352      }
353  
354      switch (offset) {
355      case A_NSCCFG:
356          s->nsccfg = value & 3;
357          qemu_set_irq(s->nsc_cfg_irq, s->nsccfg);
358          break;
359      case A_SECRESPCFG:
360          value &= 1;
361          s->secrespcfg = value;
362          qemu_set_irq(s->sec_resp_cfg, s->secrespcfg);
363          break;
364      case A_SECPPCINTCLR:
365          s->secppcintstat &= ~(value & 0x00f000f3);
366          foreach_ppc(s, iotkit_secctl_ppc_update_irq_clear);
367          break;
368      case A_SECPPCINTEN:
369          s->secppcinten = value & 0x00f000f3;
370          foreach_ppc(s, iotkit_secctl_ppc_update_irq_enable);
371          break;
372      case A_BRGINTCLR:
373          break;
374      case A_BRGINTEN:
375          s->brginten = value & 0xffff0000;
376          break;
377      case A_AHBNSPPCEXP0:
378      case A_AHBNSPPCEXP1:
379      case A_AHBNSPPCEXP2:
380      case A_AHBNSPPCEXP3:
381          ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
382          iotkit_secctl_ppc_ns_write(ppc, value);
383          break;
384      case A_APBNSPPC0:
385      case A_APBNSPPC1:
386          ppc = &s->apb[offset_to_ppc_idx(offset)];
387          iotkit_secctl_ppc_ns_write(ppc, value);
388          break;
389      case A_APBNSPPCEXP0:
390      case A_APBNSPPCEXP1:
391      case A_APBNSPPCEXP2:
392      case A_APBNSPPCEXP3:
393          ppc = &s->apbexp[offset_to_ppc_idx(offset)];
394          iotkit_secctl_ppc_ns_write(ppc, value);
395          break;
396      case A_AHBSPPPCEXP0:
397      case A_AHBSPPPCEXP1:
398      case A_AHBSPPPCEXP2:
399      case A_AHBSPPPCEXP3:
400          ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
401          iotkit_secctl_ppc_sp_write(ppc, value);
402          break;
403      case A_APBSPPPC0:
404      case A_APBSPPPC1:
405          ppc = &s->apb[offset_to_ppc_idx(offset)];
406          iotkit_secctl_ppc_sp_write(ppc, value);
407          break;
408      case A_APBSPPPCEXP0:
409      case A_APBSPPPCEXP1:
410      case A_APBSPPPCEXP2:
411      case A_APBSPPPCEXP3:
412          ppc = &s->apbexp[offset_to_ppc_idx(offset)];
413          iotkit_secctl_ppc_sp_write(ppc, value);
414          break;
415      case A_SECMSCINTCLR:
416          iotkit_secctl_update_mscexp_irqs(s->mscexp_clear, value);
417          break;
418      case A_SECMSCINTEN:
419          s->secmscinten = value;
420          iotkit_secctl_update_msc_irq(s);
421          break;
422      case A_NSMSCEXP:
423          s->nsmscexp = value;
424          iotkit_secctl_update_mscexp_irqs(s->mscexp_ns, value);
425          break;
426      case A_SECMPCINTSTATUS:
427      case A_SECPPCINTSTAT:
428      case A_SECMSCINTSTAT:
429      case A_BRGINTSTAT:
430      case A_AHBNSPPC0:
431      case A_AHBSPPPC0:
432      case A_PID4:
433      case A_PID5:
434      case A_PID6:
435      case A_PID7:
436      case A_PID0:
437      case A_PID1:
438      case A_PID2:
439      case A_PID3:
440      case A_CID0:
441      case A_CID1:
442      case A_CID2:
443      case A_CID3:
444          qemu_log_mask(LOG_GUEST_ERROR,
445                        "IoTKit SecCtl S block write: "
446                        "read-only offset 0x%x\n", offset);
447          break;
448      default:
449          qemu_log_mask(LOG_GUEST_ERROR,
450                        "IotKit SecCtl S block write: bad offset 0x%x\n",
451                        offset);
452          break;
453      }
454  
455      return MEMTX_OK;
456  }
457  
iotkit_secctl_ns_read(void * opaque,hwaddr addr,uint64_t * pdata,unsigned size,MemTxAttrs attrs)458  static MemTxResult iotkit_secctl_ns_read(void *opaque, hwaddr addr,
459                                           uint64_t *pdata,
460                                           unsigned size, MemTxAttrs attrs)
461  {
462      IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
463      uint64_t r;
464      uint32_t offset = addr & ~0x3;
465  
466      switch (offset) {
467      case A_AHBNSPPPC0:
468          r = 0;
469          break;
470      case A_AHBNSPPPCEXP0:
471      case A_AHBNSPPPCEXP1:
472      case A_AHBNSPPPCEXP2:
473      case A_AHBNSPPPCEXP3:
474          r = s->ahbexp[offset_to_ppc_idx(offset)].nsp;
475          break;
476      case A_APBNSPPPC0:
477      case A_APBNSPPPC1:
478          r = s->apb[offset_to_ppc_idx(offset)].nsp;
479          break;
480      case A_APBNSPPPCEXP0:
481      case A_APBNSPPPCEXP1:
482      case A_APBNSPPPCEXP2:
483      case A_APBNSPPPCEXP3:
484          r = s->apbexp[offset_to_ppc_idx(offset)].nsp;
485          break;
486      case A_PID4:
487      case A_PID5:
488      case A_PID6:
489      case A_PID7:
490      case A_PID0:
491      case A_PID1:
492      case A_PID2:
493      case A_PID3:
494      case A_CID0:
495      case A_CID1:
496      case A_CID2:
497      case A_CID3:
498          switch (s->sse_version) {
499          case ARMSSE_SSE300:
500              r = iotkit_secctl_ns_sse300_idregs[(offset - A_PID4) / 4];
501              break;
502          default:
503              r = iotkit_secctl_ns_idregs[(offset - A_PID4) / 4];
504              break;
505          }
506          break;
507      default:
508          qemu_log_mask(LOG_GUEST_ERROR,
509                        "IotKit SecCtl NS block write: bad offset 0x%x\n",
510                        offset);
511          r = 0;
512          break;
513      }
514  
515      if (size != 4) {
516          /* None of our registers are access-sensitive, so just pull the right
517           * byte out of the word read result.
518           */
519          r = extract32(r, (addr & 3) * 8, size * 8);
520      }
521  
522      trace_iotkit_secctl_ns_read(offset, r, size);
523      *pdata = r;
524      return MEMTX_OK;
525  }
526  
iotkit_secctl_ns_write(void * opaque,hwaddr addr,uint64_t value,unsigned size,MemTxAttrs attrs)527  static MemTxResult iotkit_secctl_ns_write(void *opaque, hwaddr addr,
528                                            uint64_t value,
529                                            unsigned size, MemTxAttrs attrs)
530  {
531      IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
532      uint32_t offset = addr;
533      IoTKitSecCtlPPC *ppc;
534  
535      trace_iotkit_secctl_ns_write(offset, value, size);
536  
537      if (size != 4) {
538          /* Byte and halfword writes are ignored */
539          qemu_log_mask(LOG_GUEST_ERROR,
540                        "IotKit SecCtl NS block write: bad size, ignored\n");
541          return MEMTX_OK;
542      }
543  
544      switch (offset) {
545      case A_AHBNSPPPCEXP0:
546      case A_AHBNSPPPCEXP1:
547      case A_AHBNSPPPCEXP2:
548      case A_AHBNSPPPCEXP3:
549          ppc = &s->ahbexp[offset_to_ppc_idx(offset)];
550          iotkit_secctl_ppc_nsp_write(ppc, value);
551          break;
552      case A_APBNSPPPC0:
553      case A_APBNSPPPC1:
554          ppc = &s->apb[offset_to_ppc_idx(offset)];
555          iotkit_secctl_ppc_nsp_write(ppc, value);
556          break;
557      case A_APBNSPPPCEXP0:
558      case A_APBNSPPPCEXP1:
559      case A_APBNSPPPCEXP2:
560      case A_APBNSPPPCEXP3:
561          ppc = &s->apbexp[offset_to_ppc_idx(offset)];
562          iotkit_secctl_ppc_nsp_write(ppc, value);
563          break;
564      case A_AHBNSPPPC0:
565      case A_PID4:
566      case A_PID5:
567      case A_PID6:
568      case A_PID7:
569      case A_PID0:
570      case A_PID1:
571      case A_PID2:
572      case A_PID3:
573      case A_CID0:
574      case A_CID1:
575      case A_CID2:
576      case A_CID3:
577          qemu_log_mask(LOG_GUEST_ERROR,
578                        "IoTKit SecCtl NS block write: "
579                        "read-only offset 0x%x\n", offset);
580          break;
581      default:
582          qemu_log_mask(LOG_GUEST_ERROR,
583                        "IotKit SecCtl NS block write: bad offset 0x%x\n",
584                        offset);
585          break;
586      }
587  
588      return MEMTX_OK;
589  }
590  
591  static const MemoryRegionOps iotkit_secctl_s_ops = {
592      .read_with_attrs = iotkit_secctl_s_read,
593      .write_with_attrs = iotkit_secctl_s_write,
594      .endianness = DEVICE_LITTLE_ENDIAN,
595      .valid.min_access_size = 1,
596      .valid.max_access_size = 4,
597      .impl.min_access_size = 1,
598      .impl.max_access_size = 4,
599  };
600  
601  static const MemoryRegionOps iotkit_secctl_ns_ops = {
602      .read_with_attrs = iotkit_secctl_ns_read,
603      .write_with_attrs = iotkit_secctl_ns_write,
604      .endianness = DEVICE_LITTLE_ENDIAN,
605      .valid.min_access_size = 1,
606      .valid.max_access_size = 4,
607      .impl.min_access_size = 1,
608      .impl.max_access_size = 4,
609  };
610  
iotkit_secctl_reset_ppc(IoTKitSecCtlPPC * ppc)611  static void iotkit_secctl_reset_ppc(IoTKitSecCtlPPC *ppc)
612  {
613      ppc->ns = 0;
614      ppc->sp = 0;
615      ppc->nsp = 0;
616  }
617  
iotkit_secctl_reset(DeviceState * dev)618  static void iotkit_secctl_reset(DeviceState *dev)
619  {
620      IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
621  
622      s->secppcintstat = 0;
623      s->secppcinten = 0;
624      s->secrespcfg = 0;
625      s->nsccfg = 0;
626      s->brginten = 0;
627  
628      foreach_ppc(s, iotkit_secctl_reset_ppc);
629  }
630  
iotkit_secctl_mpc_status(void * opaque,int n,int level)631  static void iotkit_secctl_mpc_status(void *opaque, int n, int level)
632  {
633      IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
634  
635      s->mpcintstatus = deposit32(s->mpcintstatus, n, 1, !!level);
636  }
637  
iotkit_secctl_mpcexp_status(void * opaque,int n,int level)638  static void iotkit_secctl_mpcexp_status(void *opaque, int n, int level)
639  {
640      IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
641  
642      s->mpcintstatus = deposit32(s->mpcintstatus, n + 16, 1, !!level);
643  }
644  
iotkit_secctl_mscexp_status(void * opaque,int n,int level)645  static void iotkit_secctl_mscexp_status(void *opaque, int n, int level)
646  {
647      IoTKitSecCtl *s = IOTKIT_SECCTL(opaque);
648  
649      s->secmscintstat = deposit32(s->secmscintstat, n + 16, 1, !!level);
650      iotkit_secctl_update_msc_irq(s);
651  }
652  
iotkit_secctl_ppc_irqstatus(void * opaque,int n,int level)653  static void iotkit_secctl_ppc_irqstatus(void *opaque, int n, int level)
654  {
655      IoTKitSecCtlPPC *ppc = opaque;
656      IoTKitSecCtl *s = IOTKIT_SECCTL(ppc->parent);
657      int irqbit = ppc->irq_bit_offset + n;
658  
659      s->secppcintstat = deposit32(s->secppcintstat, irqbit, 1, level);
660  }
661  
iotkit_secctl_init_ppc(IoTKitSecCtl * s,IoTKitSecCtlPPC * ppc,const char * name,int numports,int irq_bit_offset)662  static void iotkit_secctl_init_ppc(IoTKitSecCtl *s,
663                                     IoTKitSecCtlPPC *ppc,
664                                     const char *name,
665                                     int numports,
666                                     int irq_bit_offset)
667  {
668      char *gpioname;
669      DeviceState *dev = DEVICE(s);
670  
671      ppc->numports = numports;
672      ppc->irq_bit_offset = irq_bit_offset;
673      ppc->parent = s;
674  
675      gpioname = g_strdup_printf("%s_nonsec", name);
676      qdev_init_gpio_out_named(dev, ppc->nonsec, gpioname, numports);
677      g_free(gpioname);
678      gpioname = g_strdup_printf("%s_ap", name);
679      qdev_init_gpio_out_named(dev, ppc->ap, gpioname, numports);
680      g_free(gpioname);
681      gpioname = g_strdup_printf("%s_irq_enable", name);
682      qdev_init_gpio_out_named(dev, &ppc->irq_enable, gpioname, 1);
683      g_free(gpioname);
684      gpioname = g_strdup_printf("%s_irq_clear", name);
685      qdev_init_gpio_out_named(dev, &ppc->irq_clear, gpioname, 1);
686      g_free(gpioname);
687      gpioname = g_strdup_printf("%s_irq_status", name);
688      qdev_init_gpio_in_named_with_opaque(dev, iotkit_secctl_ppc_irqstatus,
689                                          ppc, gpioname, 1);
690      g_free(gpioname);
691  }
692  
iotkit_secctl_init(Object * obj)693  static void iotkit_secctl_init(Object *obj)
694  {
695      IoTKitSecCtl *s = IOTKIT_SECCTL(obj);
696      SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
697      DeviceState *dev = DEVICE(obj);
698      int i;
699  
700      iotkit_secctl_init_ppc(s, &s->apb[0], "apb_ppc0",
701                             IOTS_APB_PPC0_NUM_PORTS, 0);
702      iotkit_secctl_init_ppc(s, &s->apb[1], "apb_ppc1",
703                             IOTS_APB_PPC1_NUM_PORTS, 1);
704  
705      for (i = 0; i < IOTS_NUM_APB_EXP_PPC; i++) {
706          IoTKitSecCtlPPC *ppc = &s->apbexp[i];
707          char *ppcname = g_strdup_printf("apb_ppcexp%d", i);
708          iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 4 + i);
709          g_free(ppcname);
710      }
711      for (i = 0; i < IOTS_NUM_AHB_EXP_PPC; i++) {
712          IoTKitSecCtlPPC *ppc = &s->ahbexp[i];
713          char *ppcname = g_strdup_printf("ahb_ppcexp%d", i);
714          iotkit_secctl_init_ppc(s, ppc, ppcname, IOTS_PPC_NUM_PORTS, 20 + i);
715          g_free(ppcname);
716      }
717  
718      qdev_init_gpio_out_named(dev, &s->sec_resp_cfg, "sec_resp_cfg", 1);
719      qdev_init_gpio_out_named(dev, &s->nsc_cfg_irq, "nsc_cfg", 1);
720  
721      qdev_init_gpio_in_named(dev, iotkit_secctl_mpc_status, "mpc_status",
722                              IOTS_NUM_MPC);
723      qdev_init_gpio_in_named(dev, iotkit_secctl_mpcexp_status,
724                              "mpcexp_status", IOTS_NUM_EXP_MPC);
725  
726      qdev_init_gpio_in_named(dev, iotkit_secctl_mscexp_status,
727                              "mscexp_status", IOTS_NUM_EXP_MSC);
728      qdev_init_gpio_out_named(dev, s->mscexp_clear, "mscexp_clear",
729                               IOTS_NUM_EXP_MSC);
730      qdev_init_gpio_out_named(dev, s->mscexp_ns, "mscexp_ns",
731                               IOTS_NUM_EXP_MSC);
732      qdev_init_gpio_out_named(dev, &s->msc_irq, "msc_irq", 1);
733  
734      memory_region_init_io(&s->s_regs, obj, &iotkit_secctl_s_ops,
735                            s, "iotkit-secctl-s-regs", 0x1000);
736      memory_region_init_io(&s->ns_regs, obj, &iotkit_secctl_ns_ops,
737                            s, "iotkit-secctl-ns-regs", 0x1000);
738      sysbus_init_mmio(sbd, &s->s_regs);
739      sysbus_init_mmio(sbd, &s->ns_regs);
740  }
741  
iotkit_secctl_realize(DeviceState * dev,Error ** errp)742  static void iotkit_secctl_realize(DeviceState *dev, Error **errp)
743  {
744      IoTKitSecCtl *s = IOTKIT_SECCTL(dev);
745  
746      if (!armsse_version_valid(s->sse_version)) {
747          error_setg(errp, "invalid sse-version value %d", s->sse_version);
748          return;
749      }
750  }
751  
752  static const VMStateDescription iotkit_secctl_ppc_vmstate = {
753      .name = "iotkit-secctl-ppc",
754      .version_id = 1,
755      .minimum_version_id = 1,
756      .fields = (const VMStateField[]) {
757          VMSTATE_UINT32(ns, IoTKitSecCtlPPC),
758          VMSTATE_UINT32(sp, IoTKitSecCtlPPC),
759          VMSTATE_UINT32(nsp, IoTKitSecCtlPPC),
760          VMSTATE_END_OF_LIST()
761      }
762  };
763  
764  static const VMStateDescription iotkit_secctl_mpcintstatus_vmstate = {
765      .name = "iotkit-secctl-mpcintstatus",
766      .version_id = 1,
767      .minimum_version_id = 1,
768      .fields = (const VMStateField[]) {
769          VMSTATE_UINT32(mpcintstatus, IoTKitSecCtl),
770          VMSTATE_END_OF_LIST()
771      }
772  };
773  
needed_always(void * opaque)774  static bool needed_always(void *opaque)
775  {
776      return true;
777  }
778  
779  static const VMStateDescription iotkit_secctl_msc_vmstate = {
780      .name = "iotkit-secctl/msc",
781      .version_id = 1,
782      .minimum_version_id = 1,
783      .needed = needed_always,
784      .fields = (const VMStateField[]) {
785          VMSTATE_UINT32(secmscintstat, IoTKitSecCtl),
786          VMSTATE_UINT32(secmscinten, IoTKitSecCtl),
787          VMSTATE_UINT32(nsmscexp, IoTKitSecCtl),
788          VMSTATE_END_OF_LIST()
789      }
790  };
791  
792  static const VMStateDescription iotkit_secctl_vmstate = {
793      .name = "iotkit-secctl",
794      .version_id = 1,
795      .minimum_version_id = 1,
796      .fields = (const VMStateField[]) {
797          VMSTATE_UINT32(secppcintstat, IoTKitSecCtl),
798          VMSTATE_UINT32(secppcinten, IoTKitSecCtl),
799          VMSTATE_UINT32(secrespcfg, IoTKitSecCtl),
800          VMSTATE_UINT32(nsccfg, IoTKitSecCtl),
801          VMSTATE_UINT32(brginten, IoTKitSecCtl),
802          VMSTATE_STRUCT_ARRAY(apb, IoTKitSecCtl, IOTS_NUM_APB_PPC, 1,
803                               iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
804          VMSTATE_STRUCT_ARRAY(apbexp, IoTKitSecCtl, IOTS_NUM_APB_EXP_PPC, 1,
805                               iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
806          VMSTATE_STRUCT_ARRAY(ahbexp, IoTKitSecCtl, IOTS_NUM_AHB_EXP_PPC, 1,
807                               iotkit_secctl_ppc_vmstate, IoTKitSecCtlPPC),
808          VMSTATE_END_OF_LIST()
809      },
810      .subsections = (const VMStateDescription * const []) {
811          &iotkit_secctl_mpcintstatus_vmstate,
812          &iotkit_secctl_msc_vmstate,
813          NULL
814      },
815  };
816  
817  static Property iotkit_secctl_props[] = {
818      DEFINE_PROP_UINT32("sse-version", IoTKitSecCtl, sse_version, 0),
819      DEFINE_PROP_END_OF_LIST()
820  };
821  
iotkit_secctl_class_init(ObjectClass * klass,void * data)822  static void iotkit_secctl_class_init(ObjectClass *klass, void *data)
823  {
824      DeviceClass *dc = DEVICE_CLASS(klass);
825  
826      dc->vmsd = &iotkit_secctl_vmstate;
827      device_class_set_legacy_reset(dc, iotkit_secctl_reset);
828      dc->realize = iotkit_secctl_realize;
829      device_class_set_props(dc, iotkit_secctl_props);
830  }
831  
832  static const TypeInfo iotkit_secctl_info = {
833      .name = TYPE_IOTKIT_SECCTL,
834      .parent = TYPE_SYS_BUS_DEVICE,
835      .instance_size = sizeof(IoTKitSecCtl),
836      .instance_init = iotkit_secctl_init,
837      .class_init = iotkit_secctl_class_init,
838  };
839  
iotkit_secctl_register_types(void)840  static void iotkit_secctl_register_types(void)
841  {
842      type_register_static(&iotkit_secctl_info);
843  }
844  
845  type_init(iotkit_secctl_register_types);
846