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

     1  // NXP i.MX6 UL/ULL/ULZ support
     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 provides support to Go bare metal unikernels written using the
    11  // TamaGo framework.
    12  //
    13  // The package implements initialization and drivers for specific NXP i.MX6
    14  // System-on-Chip (SoC) peripherals, adopting, where indicated, the following
    15  // reference specifications:
    16  //   * IMX6ULLRM  - i.MX 6ULL Applications Processor Reference Manual                - Rev 1      2017/11
    17  //   * IMX6FG     - i.MX 6 Series Firmware Guide                                     - Rev 0      2012/11
    18  //   * IMX6ULLCEC - i.MX6ULL Data Sheet                                              - Rev 1.2    2017/11
    19  //   * MCIMX28RM  - i.MX28 Applications Processor Reference Manual                   - Rev 2      2013/08
    20  //   * SD-PL-7.10 - SD Specifications Part 1 Physical Layer Simplified Specification - 7.10       2020/03/25
    21  //   * JESD84-B51 - Embedded Multi-Media Card (e•MMC) Electrical Standard (5.1)      - JESD84-B51 2015/02
    22  //   * USB2.0     - USB Specification Revision 2.0                                   - 2.0        2000/04/27
    23  //
    24  // This package is only meant to be used with `GOOS=tamago GOARCH=arm` as
    25  // supported by the TamaGo framework for bare metal Go on ARM SoCs, see
    26  // https://github.com/f-secure-foundry/tamago.
    27  package imx6
    28  
    29  import (
    30  	"encoding/binary"
    31  	_ "unsafe"
    32  
    33  	"github.com/f-secure-foundry/tamago/arm"
    34  	"github.com/f-secure-foundry/tamago/internal/reg"
    35  )
    36  
    37  // Identification registers
    38  const (
    39  	OCOTP_CFG0         = 0x021bc410
    40  	OCOTP_CFG1         = 0x021bc420
    41  	USB_ANALOG_DIGPROG = 0x020c8260
    42  )
    43  
    44  const (
    45  	// GIC base address (p176, Table 2-1, IMX6ULLRM)
    46  	GIC_BASE = 0x00a00000
    47  
    48  	// Timer registers (p178, Table 2-3, IMX6ULLRM)
    49  	SYS_CNT_BASE = 0x021dc000
    50  )
    51  
    52  // i.MX processor families
    53  const (
    54  	IMX6UL  = 0x64
    55  	IMX6ULL = 0x65
    56  )
    57  
    58  // Processor family
    59  var Family uint32
    60  
    61  // Flag for native or emulated processor
    62  var Native bool
    63  
    64  // ARM processor instance
    65  var ARM = &arm.CPU{}
    66  
    67  //go:linkname nanotime1 runtime.nanotime1
    68  func nanotime1() int64 {
    69  	return int64(ARM.TimerFn()*ARM.TimerMultiplier + ARM.TimerOffset)
    70  }
    71  
    72  // Init takes care of the lower level SoC initialization triggered early in
    73  // runtime setup.
    74  func Init() {
    75  	if ARM.Mode() != arm.SYS_MODE {
    76  		// initialization required only when in PL1
    77  		return
    78  	}
    79  
    80  	ARM.Init()
    81  	ARM.EnableVFP()
    82  
    83  	// required when booting in SDP mode
    84  	ARM.EnableSMP()
    85  
    86  	// MMU initialization is required to take advantage of data cache
    87  	ARM.InitMMU()
    88  	ARM.EnableCache()
    89  
    90  	_, fam, revMajor, revMinor := SiliconVersion()
    91  	Family = fam
    92  
    93  	if revMajor != 0 || revMinor != 0 {
    94  		Native = true
    95  	}
    96  
    97  	switch Family {
    98  	case IMX6UL, IMX6ULL:
    99  		if !Native {
   100  			// use QEMU fixed CNTFRQ value (62.5MHz)
   101  			ARM.InitGenericTimers(SYS_CNT_BASE, 62500000)
   102  		} else {
   103  			// U-Boot value for i.MX6 family (8.0MHz)
   104  			ARM.InitGenericTimers(SYS_CNT_BASE, 8000000)
   105  		}
   106  	default:
   107  		ARM.InitGlobalTimers()
   108  	}
   109  }
   110  
   111  // SiliconVersion returns the SoC silicon version information
   112  // (p3945, 57.4.11 Chip Silicon Version (USB_ANALOG_DIGPROG), IMX6ULLRM).
   113  func SiliconVersion() (sv, family, revMajor, revMinor uint32) {
   114  	sv = reg.Read(USB_ANALOG_DIGPROG)
   115  
   116  	family = (sv >> 16) & 0xff
   117  	revMajor = (sv >> 8) & 0xff
   118  	revMinor = sv & 0xff
   119  
   120  	return
   121  }
   122  
   123  // UniqueID returns the NXP SoC Device Unique 64-bit ID.
   124  func UniqueID() (uid [8]byte) {
   125  	cfg0 := reg.Read(OCOTP_CFG0)
   126  	cfg1 := reg.Read(OCOTP_CFG1)
   127  
   128  	binary.LittleEndian.PutUint32(uid[0:4], cfg0)
   129  	binary.LittleEndian.PutUint32(uid[4:8], cfg1)
   130  
   131  	return
   132  }
   133  
   134  // Model returns the SoC model name.
   135  func Model() (model string) {
   136  	switch Family {
   137  	case IMX6UL:
   138  		model = "i.MX6UL"
   139  	case IMX6ULL:
   140  		model = "i.MX6ULL"
   141  	default:
   142  		model = "unknown"
   143  	}
   144  
   145  	return
   146  }