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