github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/soc/bcm2835/miniuart.go (about)

     1  // BCM2835 mini-UART driver
     2  // https://github.com/f-secure-foundry/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  // This mini-UART is specifically intended for use as a
    10  // console. See BCM2835-ARM-Peripherals.pdf that is
    11  // widely available.
    12  //
    13  
    14  package bcm2835
    15  
    16  import (
    17  	"github.com/f-secure-foundry/tamago/arm"
    18  	"github.com/f-secure-foundry/tamago/internal/reg"
    19  )
    20  
    21  const (
    22  	AUX_ENABLES     = 0x215004
    23  	AUX_MU_IO_REG   = 0x215040
    24  	AUX_MU_IER_REG  = 0x215044
    25  	AUX_MU_IIR_REG  = 0x215048
    26  	AUX_MU_LCR_REG  = 0x21504C
    27  	AUX_MU_MCR_REG  = 0x215050
    28  	AUX_MU_LSR_REG  = 0x215054
    29  	AUX_MU_MSR_REG  = 0x215058
    30  	AUX_MU_SCRATCH  = 0x21505C
    31  	AUX_MU_CNTL_REG = 0x215060
    32  	AUX_MU_STAT_REG = 0x215064
    33  	AUX_MU_BAUD_REG = 0x215068
    34  )
    35  
    36  type miniUART struct {
    37  	lsr uint32
    38  	io  uint32
    39  }
    40  
    41  // MiniUART is a secondary low throughput UART intended to be
    42  // used as a console.
    43  var MiniUART = &miniUART{}
    44  
    45  // Init initializes the MiniUART.
    46  func (hw *miniUART) Init() {
    47  	reg.Write(PeripheralAddress(AUX_ENABLES), 1)
    48  	reg.Write(PeripheralAddress(AUX_MU_IER_REG), 0)
    49  	reg.Write(PeripheralAddress(AUX_MU_CNTL_REG), 0)
    50  	reg.Write(PeripheralAddress(AUX_MU_LCR_REG), 3)
    51  	reg.Write(PeripheralAddress(AUX_MU_MCR_REG), 0)
    52  	reg.Write(PeripheralAddress(AUX_MU_IER_REG), 0)
    53  	reg.Write(PeripheralAddress(AUX_MU_IIR_REG), 0xc6)
    54  	reg.Write(PeripheralAddress(AUX_MU_BAUD_REG), 270)
    55  
    56  	// Not using GPIO abstraction here because at the point
    57  	// we initialize mini-UART during initialization, to
    58  	// provide 'console', calling Lock on sync.Mutex fails.
    59  	ra := reg.Read(PeripheralAddress(GPFSEL1))
    60  	ra &= ^(uint32(7) << 12) // gpio14
    61  	ra |= 2 << 12            // alt5
    62  	ra &= ^(uint32(7) << 15) // gpio15
    63  	ra |= 2 << 15            // alt5
    64  	reg.Write(PeripheralAddress(GPFSEL1), ra)
    65  
    66  	reg.Write(PeripheralAddress(GPPUD), 0)
    67  	arm.Busyloop(150)
    68  
    69  	reg.Write(PeripheralAddress(GPPUDCLK0), (1<<14)|(1<<15))
    70  	arm.Busyloop(150)
    71  
    72  	reg.Write(PeripheralAddress(GPPUDCLK0), 0)
    73  	reg.Write(PeripheralAddress(AUX_MU_CNTL_REG), 3)
    74  
    75  	hw.lsr = PeripheralAddress(AUX_MU_LSR_REG)
    76  	hw.io = PeripheralAddress(AUX_MU_IO_REG)
    77  }
    78  
    79  // TX transmits a single character to the serial port.
    80  func (hw *miniUART) Tx(c byte) {
    81  	for {
    82  		if reg.Read(hw.lsr)&0x20 != 0 {
    83  			break
    84  		}
    85  	}
    86  
    87  	reg.Write(hw.io, uint32(c))
    88  }
    89  
    90  // Write data from buffer to serial port.
    91  func (hw *miniUART) Write(buf []byte) {
    92  	for i := 0; i < len(buf); i++ {
    93  		hw.Tx(buf[i])
    94  	}
    95  }