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

     1  // NXP i.MX6 UART driver
     2  // https://github.com/f-secure-foundry/tamago
     3  //
     4  // Copyright (c) F-Secure Corporation
     5  // https://foundry.f-secure.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 imx6
    11  
    12  import (
    13  	"sync"
    14  
    15  	"github.com/f-secure-foundry/tamago/bits"
    16  	"github.com/f-secure-foundry/tamago/internal/reg"
    17  )
    18  
    19  // UART registers
    20  const (
    21  	UART_DEFAULT_BAUDRATE = 115200
    22  	ESC                   = 0x1b
    23  
    24  	// p3608, 55.15 UART Memory Map/Register Definition, IMX6ULLRM
    25  
    26  	// i.MX 6UltraLite (G0, G1, G2, G3, G4)
    27  	// i.MX 6ULL (Y0, Y1, Y2)
    28  	// i.MX 6ULZ (Z0)
    29  	UART1_BASE = 0x02020000
    30  	UART2_BASE = 0x021e8000
    31  	UART3_BASE = 0x021ec000
    32  	UART4_BASE = 0x021f0000
    33  
    34  	// i.MX 6UltraLite (G1, G2, G3, G4)
    35  	// i.MX 6ULL (Y1, Y2)
    36  	UART5_BASE = 0x021f4000
    37  	UART6_BASE = 0x021fc000
    38  	UART7_BASE = 0x02018000
    39  	UART8_BASE = 0x02024000
    40  
    41  	UARTx_URXD   = 0x0000
    42  	URXD_CHARRDY = 15
    43  	URXD_ERR     = 14
    44  	URXD_OVRRUN  = 13
    45  	URXD_FRMERR  = 12
    46  	URXD_BRK     = 11
    47  	URXD_PRERR   = 10
    48  	URXD_RX_DATA = 0
    49  
    50  	UARTx_UTXD   = 0x0040
    51  	UTXD_TX_DATA = 0
    52  
    53  	UARTx_UCR1    = 0x0080
    54  	UCR1_ADEN     = 15
    55  	UCR1_ADBR     = 14
    56  	UCR1_TRDYEN   = 13
    57  	UCR1_IDEN     = 12
    58  	UCR1_ICD      = 10
    59  	UCR1_RRDYEN   = 9
    60  	UCR1_RXDMAEN  = 8
    61  	UCR1_IREN     = 7
    62  	UCR1_TXMPTYEN = 6
    63  	UCR1_RTSDEN   = 5
    64  	UCR1_SNDBRK   = 4
    65  	UCR1_TXDMAEN  = 3
    66  	UCR1_ATDMAEN  = 2
    67  	UCR1_DOZE     = 1
    68  	UCR1_UARTEN   = 0
    69  
    70  	UARTx_UCR2 = 0x0084
    71  	UCR2_ESCI  = 15
    72  	UCR2_IRTS  = 14
    73  	UCR2_CTSC  = 13
    74  	UCR2_CTS   = 12
    75  	UCR2_ESCEN = 11
    76  	UCR2_RTEC  = 9
    77  	UCR2_PREN  = 8
    78  	UCR2_PROE  = 7
    79  	UCR2_STPB  = 6
    80  	UCR2_WS    = 5
    81  	UCR2_RTSEN = 4
    82  	UCR2_ATEN  = 3
    83  	UCR2_TXEN  = 2
    84  	UCR2_RXEN  = 1
    85  	UCR2_SRST  = 0
    86  
    87  	UARTx_UCR3     = 0x0088
    88  	UCR3_DPEC      = 14
    89  	UCR3_DTREN     = 13
    90  	UCR3_PARERREN  = 12
    91  	UCR3_FRAERREN  = 11
    92  	UCR3_DSR       = 10
    93  	UCR3_DCD       = 9
    94  	UCR3_RI        = 8
    95  	UCR3_ADNIMP    = 7
    96  	UCR3_RXDSEN    = 6
    97  	UCR3_AIRINTEN  = 5
    98  	UCR3_AWAKEN    = 4
    99  	UCR3_DTRDEN    = 3
   100  	UCR3_RXDMUXSEL = 2
   101  	UCR3_INVT      = 1
   102  	UCR3_ACIEN     = 0
   103  
   104  	UARTx_UCR4 = 0x008c
   105  	UCR4_CTSTL = 10
   106  
   107  	UARTx_UFCR  = 0x0090
   108  	UFCR_TXTL   = 10
   109  	UFCR_RFDIV  = 7
   110  	UFCR_DCEDTE = 6
   111  	UFCR_RXTL   = 0
   112  
   113  	UARTx_USR2 = 0x0098
   114  	USR2_RDR   = 0
   115  
   116  	UARTx_UESC = 0x009c
   117  	UARTx_UTIM = 0x00a0
   118  	UARTx_UBIR = 0x00a4
   119  	UARTx_UBMR = 0x00a8
   120  
   121  	UARTx_UTS  = 0x00b4
   122  	UTS_TXFULL = 4
   123  )
   124  
   125  // UART represents a serial port instance
   126  type UART struct {
   127  	sync.Mutex
   128  
   129  	// controller index
   130  	n int
   131  
   132  	// port speed
   133  	Baudrate uint32
   134  	// DTE mode
   135  	DTE bool
   136  	// hardware flow control
   137  	Flow bool
   138  
   139  	// control registers
   140  	urxd uint32
   141  	utxd uint32
   142  	ucr1 uint32
   143  	ucr2 uint32
   144  	ucr3 uint32
   145  	ucr4 uint32
   146  	ufcr uint32
   147  	usr2 uint32
   148  	uesc uint32
   149  	utim uint32
   150  	ubir uint32
   151  	ubmr uint32
   152  	uts  uint32
   153  }
   154  
   155  // UART1 instance
   156  var UART1 = &UART{
   157  	n:        1,
   158  	Baudrate: UART_DEFAULT_BAUDRATE,
   159  }
   160  
   161  // UART2 instance
   162  var UART2 = &UART{
   163  	n:        2,
   164  	Baudrate: UART_DEFAULT_BAUDRATE,
   165  }
   166  
   167  // Init initializes and enables the UART for RS-232 mode,
   168  // p3605, 55.13.1 Programming the UART in RS-232 mode, IMX6ULLRM.
   169  func (hw *UART) Init() {
   170  	var base uint32
   171  
   172  	hw.Lock()
   173  
   174  	switch hw.n {
   175  	case 1:
   176  		base = UART1_BASE
   177  	case 2:
   178  		base = UART2_BASE
   179  	case 3:
   180  		base = UART3_BASE
   181  	case 4:
   182  		base = UART4_BASE
   183  	default:
   184  		panic("invalid UART controller instance")
   185  	}
   186  
   187  	hw.urxd = base + UARTx_URXD
   188  	hw.utxd = base + UARTx_UTXD
   189  	hw.ucr1 = base + UARTx_UCR1
   190  	hw.ucr2 = base + UARTx_UCR2
   191  	hw.ucr3 = base + UARTx_UCR3
   192  	hw.ucr4 = base + UARTx_UCR4
   193  	hw.ufcr = base + UARTx_UFCR
   194  	hw.usr2 = base + UARTx_USR2
   195  	hw.uesc = base + UARTx_UESC
   196  	hw.utim = base + UARTx_UTIM
   197  	hw.ubir = base + UARTx_UBIR
   198  	hw.ubmr = base + UARTx_UBMR
   199  	hw.uts = base + UARTx_UTS
   200  
   201  	hw.setup()
   202  
   203  	hw.Unlock()
   204  }
   205  
   206  func uartclk() uint32 {
   207  	var freq uint32
   208  
   209  	if reg.Get(CCM_CSCDR1, CSCDR1_UART_CLK_SEL, 0b1) == 1 {
   210  		freq = OSC_FREQ
   211  	} else {
   212  		// match /6 static divider (p630, Figure 18-3. Clock Tree - Part 2, IMX6ULLRM)
   213  		freq = PLL3_FREQ / 6
   214  	}
   215  
   216  	podf := reg.Get(CCM_CSCDR1, CSCDR1_UART_CLK_PODF, 0b111111)
   217  
   218  	return freq / (podf + 1)
   219  }
   220  
   221  func (hw *UART) txFull() bool {
   222  	return reg.Get(hw.uts, UTS_TXFULL, 1) == 1
   223  }
   224  
   225  func (hw *UART) rxReady() bool {
   226  	return reg.Get(hw.usr2, USR2_RDR, 1) == 1
   227  }
   228  
   229  func (hw *UART) setup() {
   230  	// disable UART
   231  	reg.Write(hw.ucr1, 0)
   232  	reg.Write(hw.ucr2, 0)
   233  
   234  	// wait for software reset deassertion
   235  	reg.Wait(hw.ucr2, UCR2_SRST, 1, 1)
   236  
   237  	var ucr3 uint32
   238  	// Data Set Ready
   239  	bits.Set(&ucr3, UCR3_DSR)
   240  	// Data Carrier Detect
   241  	bits.Set(&ucr3, UCR3_DCD)
   242  	// Ring Indicator
   243  	bits.Set(&ucr3, UCR3_RI)
   244  	// Disable autobaud detection
   245  	bits.Set(&ucr3, UCR3_ADNIMP)
   246  	// UART is in MUXED mode
   247  	bits.Set(&ucr3, UCR3_RXDMUXSEL)
   248  	// set UCR3
   249  	reg.Write(hw.ucr3, ucr3)
   250  
   251  	// set escape character
   252  	reg.Write(hw.uesc, ESC)
   253  	// reset escape timer
   254  	reg.Write(hw.utim, 0)
   255  
   256  	var ufcr uint32
   257  	// Divide input clock by 2
   258  	bits.SetN(&ufcr, UFCR_RFDIV, 0b111, 0b100)
   259  	// TxFIFO has 2 or fewer characters
   260  	bits.SetN(&ufcr, UFCR_TXTL, 0b111111, 2)
   261  	// RxFIFO has 1 character
   262  	bits.SetN(&ufcr, UFCR_RXTL, 0b111111, 1)
   263  
   264  	if hw.DTE {
   265  		bits.Set(&ufcr, UFCR_DCEDTE)
   266  	}
   267  
   268  	// set UFCR
   269  	reg.Write(hw.ufcr, ufcr)
   270  
   271  	// p3592, 55.5 Binary Rate Multiplier (BRM), IMX6ULLRM
   272  	//
   273  	//              ref_clk_freq
   274  	// baudrate = -----------------
   275  	//                   UBMR + 1
   276  	//             16 * ----------
   277  	//                   UBIR + 1
   278  	//
   279  	// ref_clk_freq = module_clock
   280  
   281  	// multiply to match UFCR_RFDIV divider value
   282  	ubmr := uartclk() / (2 * hw.Baudrate)
   283  	// neutralize denominator
   284  	reg.Write(hw.ubir, 15)
   285  	// set UBMR
   286  	reg.Write(hw.ubmr, ubmr)
   287  
   288  	var ucr2 uint32
   289  	// 8-bit transmit and receive character length
   290  	bits.Set(&ucr2, UCR2_WS)
   291  	// Enable the transmitter
   292  	bits.Set(&ucr2, UCR2_TXEN)
   293  	// Enable the receiver
   294  	bits.Set(&ucr2, UCR2_RXEN)
   295  	// Software reset
   296  	bits.Set(&ucr2, UCR2_SRST)
   297  
   298  	if hw.Flow {
   299  		// Receiver controls CTS
   300  		bits.Set(&ucr2, UCR2_CTSC)
   301  
   302  		// 16 characters in the RxFIFO as the maximum value leads to
   303  		// overflow even with hardware flow control in place.
   304  		reg.SetN(hw.ucr4, UCR4_CTSTL, 0b111111, 16)
   305  	} else {
   306  		// Ignore the RTS pin
   307  		bits.Set(&ucr2, UCR2_IRTS)
   308  
   309  		// 32 characters in the RxFIFO (maximum)
   310  		reg.SetN(hw.ucr4, UCR4_CTSTL, 0b111111, 32)
   311  	}
   312  
   313  	// set UCR2
   314  	reg.Write(hw.ucr2, ucr2)
   315  	// Enable the UART
   316  	reg.Set(hw.ucr1, UCR1_UARTEN)
   317  }
   318  
   319  // Enable enables the UART, this is only required after an explicit disable
   320  // (see Disable()) as initialized interfaces (see Init()) are enabled by default.
   321  func (hw *UART) Enable() {
   322  	reg.Set(hw.ucr1, UCR1_UARTEN)
   323  }
   324  
   325  // Disable disables the UART.
   326  func (hw *UART) Disable() {
   327  	reg.Clear(hw.ucr1, UCR1_UARTEN)
   328  }
   329  
   330  // Tx transmits a single character to the serial port.
   331  func (hw *UART) Tx(c byte) {
   332  	for hw.txFull() {
   333  		// wait for TX FIFO to have room for a character
   334  	}
   335  	reg.Write(hw.utxd, uint32(c))
   336  }
   337  
   338  // Rx receives a single character from the serial port.
   339  func (hw *UART) Rx() (c byte, valid bool) {
   340  	if !hw.rxReady() {
   341  		return
   342  	}
   343  
   344  	urxd := reg.Read(hw.urxd)
   345  
   346  	if bits.Get(&urxd, URXD_PRERR, 0b11111) != 0 {
   347  		return
   348  	}
   349  
   350  	return byte(bits.Get(&urxd, URXD_RX_DATA, 0xff)), true
   351  }
   352  
   353  // Write data from buffer to serial port.
   354  func (hw *UART) Write(buf []byte) {
   355  	for i := 0; i < len(buf); i++ {
   356  		hw.Tx(buf[i])
   357  	}
   358  }
   359  
   360  // Read available data to buffer from serial port.
   361  func (hw *UART) Read(buf []byte) (n int) {
   362  	var valid bool
   363  
   364  	for n = 0; n < len(buf); n++ {
   365  		buf[n], valid = hw.Rx()
   366  
   367  		if !valid {
   368  			break
   369  		}
   370  	}
   371  
   372  	return
   373  }