github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/nxp/caam/job.go (about) 1 // NXP Cryptographic Acceleration and Assurance Module (CAAM) driver 2 // https://github.com/usbarmory/tamago 3 // 4 // Copyright (c) WithSecure Corporation 5 // https://foundry.withsecure.com 6 // 7 // Use of this source code is governed by the license 8 // that can be found in the LICENSE file. 9 10 package caam 11 12 import ( 13 "fmt" 14 "sync" 15 16 "github.com/usbarmory/tamago/dma" 17 "github.com/usbarmory/tamago/internal/reg" 18 ) 19 20 // CAAM Job Ring registers 21 const ( 22 CAAM_JR0_MIDR_MS = 0x10 23 CAAM_JR1_MIDR_MS = 0x18 24 CAAM_JR2_MIDR_MS = 0x20 25 26 JRxMIDR_MS_JROWN_NS = 3 27 28 CAAM_JRSTART = 0x5c 29 30 CAAM_JR0_BASE = 0x1000 31 CAAM_JR1_BASE = 0x2000 32 CAAM_JR2_BASE = 0x3000 33 34 CAAM_IRBAR_JRx = 0x04 35 CAAM_IRSR_JRx = 0x0c 36 CAAM_IRJAR_JRx = 0x1c 37 CAAM_ORBAR_JRx = 0x24 38 CAAM_ORSR_JRx = 0x2c 39 CAAM_ORJRR_JRx = 0x34 40 CAAM_ORSFR_JRx = 0x3c 41 ) 42 43 const ( 44 jobRingInterface = CAAM_JR0_BASE 45 jobRingSize = 1 46 jobWords = 1 47 jobResultWords = 2 48 ) 49 50 var once sync.Once 51 52 type jobRing struct { 53 sync.Mutex 54 55 // base register 56 base uint32 57 58 // control registers 59 irjar uint32 60 orjrr uint32 61 orsfr uint32 62 63 // input/output ring size 64 size int 65 // job queue 66 input uint32 67 // results queue 68 output uint32 69 } 70 71 func (ring *jobRing) initQueue(words int, size int) uint32 { 72 buf := make([]byte, size*words*4) 73 return uint32(dma.Alloc(buf, 4)) 74 } 75 76 func (ring *jobRing) init(base uint32, size int) { 77 ring.base = base 78 ring.irjar = ring.base + CAAM_IRJAR_JRx 79 ring.orjrr = ring.base + CAAM_ORJRR_JRx 80 ring.orsfr = ring.base + CAAM_ORSFR_JRx 81 82 if ring.size > 0 { 83 dma.Free(uint(ring.input)) 84 dma.Free(uint(ring.output)) 85 } 86 87 ring.size = size 88 ring.input = ring.initQueue(jobWords, ring.size) 89 ring.output = ring.initQueue(jobResultWords, ring.size) 90 91 reg.Write(ring.base+CAAM_IRBAR_JRx, ring.input) 92 reg.Write(ring.base+CAAM_IRSR_JRx, uint32(ring.size)) 93 94 reg.Write(ring.base+CAAM_ORBAR_JRx, ring.output) 95 reg.Write(ring.base+CAAM_ORSFR_JRx, uint32(ring.size)) 96 } 97 98 func (ring *jobRing) add(hdr *Header, jd []byte) (err error) { 99 if hdr == nil { 100 hdr = &Header{} 101 hdr.SetDefaults() 102 hdr.Length(1 + len(jd)/4) 103 } 104 105 jd = append(hdr.Bytes(), jd...) 106 107 ptr := dma.Alloc(jd, 4) 108 defer dma.Free(ptr) 109 110 ring.Lock() 111 defer ring.Unlock() 112 113 // add job descriptor to input ring 114 reg.Write(ring.input, uint32(ptr)) 115 116 // signal job addition 117 reg.Write(ring.irjar, 1) 118 defer reg.Write(ring.orjrr, 1) 119 120 // wait for job completion 121 reg.Wait(ring.orsfr, 0, 0x3ff, 1) 122 123 if res := reg.Read(ring.output); res != uint32(ptr) { 124 return fmt.Errorf("CAAM job error, invalid output descriptor") 125 } 126 127 if status := reg.Read(ring.output + 4); status != 0 { 128 return fmt.Errorf("CAAM job error, status:%#x", status) 129 } 130 131 return 132 } 133 134 func (hw *CAAM) initJobRing() { 135 // start is required to enable access to job ring registers 136 startJRx := (jobRingInterface >> 12) - 1 137 138 jrstart := hw.Base + CAAM_JRSTART 139 reg.Clear(jrstart, startJRx) 140 reg.Set(jrstart, startJRx) 141 142 hw.jr = &jobRing{} 143 hw.jr.init(hw.Base+jobRingInterface, jobRingSize) 144 145 // initialize internal RNG access, required for certain CAAM commands 146 hw.initRNG() 147 } 148 149 func (hw *CAAM) job(hdr *Header, jd []byte) (err error) { 150 once.Do(hw.initJobRing) 151 return hw.jr.add(hdr, jd) 152 } 153 154 // SetOwner defines the bus master that is permitted to access CAAM job ring 155 // registers. The argument defines either secure (e.g. TrustZone Secure World) 156 // or non-secure (e.g. TrustZone Normal World) ownership. 157 func (hw *CAAM) SetOwner(secure bool) { 158 reg.SetTo(hw.Base+CAAM_JR0_MIDR_MS, JRxMIDR_MS_JROWN_NS, !secure) 159 hw.initJobRing() 160 }