github.com/usbarmory/tamago@v0.0.0-20240508072735-8612bbe1e454/soc/bcm2835/rng.go (about) 1 // BCM2835 SoC Random Number Generator (RNG) driver 2 // https://github.com/usbarmory/tamago 3 // 4 // Copyright (c) the bcm2835 package authors 5 // 6 // Use of this source code is governed by the license 7 // that can be found in the LICENSE file. 8 9 package bcm2835 10 11 import ( 12 "sync" 13 _ "unsafe" 14 15 "github.com/usbarmory/tamago/internal/reg" 16 "github.com/usbarmory/tamago/internal/rng" 17 ) 18 19 // RNG registers 20 const ( 21 RNG_BASE = 0x104000 22 23 RNG_CTRL = RNG_BASE + 0x0 24 CTRL_EN = 1 25 26 RNG_STATUS = RNG_BASE + 0x4 27 RNG_DATA = RNG_BASE + 0x8 28 ) 29 30 const warmupCount = 0x40000 31 32 // Rng represents a Random number generator instance 33 type Rng struct { 34 sync.Mutex 35 36 status uint32 37 data uint32 38 ctrl uint32 39 } 40 41 //go:linkname initRNG runtime.initRNG 42 func initRNG() { 43 r := &Rng{} 44 r.Init() 45 46 rng.GetRandomDataFn = r.getRandomData 47 } 48 49 // Init initializes the RNG by discarding 'warmup bytes'. 50 func (hw *Rng) Init() { 51 hw.Lock() 52 defer hw.Unlock() 53 54 hw.status = PeripheralAddress(RNG_STATUS) 55 hw.data = PeripheralAddress(RNG_DATA) 56 hw.ctrl = PeripheralAddress(RNG_CTRL) 57 58 // Discard 59 reg.Write(hw.status, warmupCount) 60 reg.Write(hw.ctrl, CTRL_EN) 61 } 62 63 func (hw *Rng) getRandomData(b []byte) { 64 hw.Lock() 65 defer hw.Unlock() 66 67 read := 0 68 need := len(b) 69 70 for read < need { 71 // Wait for at least one word to be available 72 for (reg.Read(hw.status) >> 24) == 0 { 73 } 74 75 read = rng.Fill(b, read, reg.Read(hw.data)) 76 } 77 }