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

     1  // NXP i.MX6 I2C 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  	"errors"
    14  	"sync"
    15  	"time"
    16  
    17  	"github.com/f-secure-foundry/tamago/internal/reg"
    18  )
    19  
    20  // I2C registers
    21  const (
    22  	// p1462, 31.7 I2C Memory Map/Register Definition, IMX6ULLRM
    23  
    24  	// i.MX 6UltraLite (G0, G1, G2, G3, G4)
    25  	// i.MX 6ULL (Y0, Y1, Y2)
    26  	// i.MX 6ULZ (Z0)
    27  	I2C1_BASE = 0x021a0000
    28  	I2C2_BASE = 0x021a4000
    29  
    30  	// i.MX 6UltraLite (G1, G2, G3, G4)
    31  	// i.MX 6ULL (Y1, Y2)
    32  	I2C3_BASE = 0x021a8000
    33  	I2C4_BASE = 0x021f8000
    34  
    35  	I2Cx_IADR = 0x0000
    36  	I2Cx_IFDR = 0x0004
    37  
    38  	I2Cx_I2CR = 0x0008
    39  	I2CR_IEN  = 7
    40  	I2CR_MSTA = 5
    41  	I2CR_MTX  = 4
    42  	I2CR_TXAK = 3
    43  	I2CR_RSTA = 2
    44  
    45  	I2Cx_I2SR = 0x000c
    46  	I2SR_IBB  = 5
    47  	I2SR_IIF  = 1
    48  	I2SR_RXAK = 0
    49  
    50  	I2Cx_I2DR = 0x0010
    51  )
    52  
    53  // I2C represents a I2C port instance.
    54  type I2C struct {
    55  	sync.Mutex
    56  
    57  	// controller index
    58  	n int
    59  	// clock gate register
    60  	ccgr uint32
    61  	// clock gate
    62  	cg int
    63  
    64  	// control registers
    65  	iadr uint32
    66  	ifdr uint32
    67  	i2cr uint32
    68  	i2sr uint32
    69  	i2dr uint32
    70  
    71  	// Timeout for I2C operations
    72  	Timeout time.Duration
    73  }
    74  
    75  // I2C1 instance
    76  var I2C1 = &I2C{n: 1}
    77  
    78  // I2C2 instance
    79  var I2C2 = &I2C{n: 2}
    80  
    81  // Init initializes the I2C controller instance. At this time only master mode
    82  // is supported by this driver.
    83  func (hw *I2C) Init() {
    84  	var base uint32
    85  
    86  	hw.Lock()
    87  	defer hw.Unlock()
    88  
    89  	switch hw.n {
    90  	case 1:
    91  		base = I2C1_BASE
    92  		hw.ccgr = CCM_CCGR2
    93  		hw.cg = CCGRx_CG3
    94  	case 2:
    95  		base = I2C2_BASE
    96  		hw.ccgr = CCM_CCGR2
    97  		hw.cg = CCGRx_CG4
    98  	case 3:
    99  		base = I2C3_BASE
   100  		hw.ccgr = CCM_CCGR2
   101  		hw.cg = CCGRx_CG5
   102  	case 4:
   103  		base = I2C4_BASE
   104  		hw.ccgr = CCM_CCGR6
   105  		hw.cg = CCGRx_CG12
   106  	default:
   107  		panic("invalid I2C controller instance")
   108  	}
   109  
   110  	hw.iadr = base + I2Cx_IADR
   111  	hw.ifdr = base + I2Cx_IFDR
   112  	hw.i2cr = base + I2Cx_I2CR
   113  	hw.i2sr = base + I2Cx_I2SR
   114  	hw.i2dr = base + I2Cx_I2DR
   115  
   116  	hw.Timeout = 100 * time.Millisecond
   117  
   118  	hw.enable()
   119  }
   120  
   121  // getRootClock returns the PERCLK_CLK_ROOT frequency,
   122  // (p629, Figure 18-2. Clock Tree - Part 1, IMX6ULLRM).
   123  func (hw *I2C) getRootClock() uint32 {
   124  	var freq uint32
   125  
   126  	if reg.Get(CCM_CSCMR1, CSCMR1_PERCLK_SEL, 1) == 1 {
   127  		freq = OSC_FREQ
   128  	} else {
   129  		// IPG_CLK_ROOT derived from AHB_CLK_ROOT which is 132 MHz
   130  		ipg_podf := reg.Get(CCM_CBCDR, CBCDR_IPG_PODF, 0b11)
   131  		freq = 132000000 / (ipg_podf + 1)
   132  	}
   133  
   134  	podf := reg.Get(CCM_CSCMR1, CSCMR1_PERCLK_PODF, 0x3f)
   135  
   136  	return freq / (podf + 1)
   137  }
   138  
   139  // p1452, 31.5.1 Initialization sequence, IMX6ULLRM
   140  func (hw *I2C) enable() {
   141  	reg.SetN(hw.ccgr, hw.cg, 0b11, 0b11)
   142  
   143  	// Set SCL frequency
   144  	// 66 MHz / 768 = 85 kbps
   145  	// TODO: allow Init() to set the baudrate.
   146  	reg.Write16(hw.ifdr, 0x16)
   147  
   148  	reg.Set16(hw.i2cr, I2CR_IEN)
   149  }
   150  
   151  // Read reads a sequence of bytes from a slave device
   152  // (p167, 16.4.2 Programming the I2C controller for I2C Read, IMX6FG).
   153  //
   154  // The return data buffer always matches the requested size, otherwise an error
   155  // is returned.
   156  //
   157  // The address length (`alen`) parameter should be set greater then 0 for
   158  // ordinary I2C reads (`SLAVE W|ADDR|SLAVE R|DATA`), equal to 0 when not
   159  // sending a register address (`SLAVE W|SLAVE R|DATA`) and less than 0 only to
   160  // send a slave read (`SLAVE R|DATA`).
   161  func (hw *I2C) Read(slave uint8, addr uint32, alen int, size int) (buf []byte, err error) {
   162  	hw.Lock()
   163  	defer hw.Unlock()
   164  
   165  	if err = hw.start(false); err != nil {
   166  		return
   167  	}
   168  	defer hw.stop()
   169  
   170  	if err = hw.txAddress(slave, addr, alen); err != nil {
   171  		return
   172  	}
   173  
   174  	if err = hw.start(true); err != nil {
   175  		return
   176  	}
   177  
   178  	// send slave address with R/W bit set
   179  	a := byte((slave << 1) | 1)
   180  
   181  	if err = hw.tx([]byte{a}); err != nil {
   182  		return
   183  	}
   184  
   185  	buf = make([]byte, size)
   186  	err = hw.rx(buf)
   187  
   188  	return
   189  }
   190  
   191  // Write writes a sequence of bytes to a slave device
   192  // (p170, 16.4.4 Programming the I2C controller for I2C Write, IMX6FG)
   193  //
   194  // Set greater then 0 for ordinary I2C write (`SLAVE W|ADDR|DATA`),
   195  // set equal then 0 to not send register address (`SLAVE W|DATA`),
   196  // alen less then 0 is invalid.
   197  //
   198  // The address length (`alen`) parameter should be set greater then 0 for
   199  // ordinary I2C writes (`SLAVE W|ADDR|DATA`), equal to 0 when not sending a
   200  // register address (`SLAVE W|DATA`), values less than 0 are not valid.
   201  func (hw *I2C) Write(buf []byte, slave uint8, addr uint32, alen int) (err error) {
   202  	if alen < 0 {
   203  		return errors.New("invalid address length")
   204  	}
   205  
   206  	hw.Lock()
   207  	defer hw.Unlock()
   208  
   209  	if err = hw.start(false); err != nil {
   210  		return
   211  	}
   212  	defer hw.stop()
   213  
   214  	if err = hw.txAddress(slave, addr, alen); err != nil {
   215  		return
   216  	}
   217  
   218  	return hw.tx(buf)
   219  }
   220  
   221  func (hw *I2C) txAddress(slave uint8, addr uint32, alen int) (err error) {
   222  	if slave > 0x7f {
   223  		return errors.New("invalid slave address")
   224  	}
   225  
   226  	if alen >= 0 {
   227  		// send slave slave address with R/W bit unset
   228  		a := byte(slave << 1)
   229  
   230  		if err = hw.tx([]byte{a}); err != nil {
   231  			return
   232  		}
   233  	}
   234  
   235  	// send register address
   236  	for alen > 0 {
   237  		alen--
   238  		a := byte(addr >> (alen * 8) & 0xff)
   239  
   240  		if err = hw.tx([]byte{a}); err != nil {
   241  			return
   242  		}
   243  	}
   244  
   245  	return
   246  }
   247  
   248  func (hw *I2C) rx(buf []byte) (err error) {
   249  	size := len(buf)
   250  
   251  	// set read from slave bit
   252  	reg.Clear16(hw.i2cr, I2CR_MTX)
   253  
   254  	if size == 1 {
   255  		reg.Set16(hw.i2cr, I2CR_TXAK)
   256  	} else {
   257  		reg.Clear16(hw.i2cr, I2CR_TXAK)
   258  	}
   259  
   260  	reg.Clear16(hw.i2sr, I2SR_IIF)
   261  	// dummy read
   262  	reg.Read16(hw.i2dr)
   263  
   264  	for i := 0; i < size; i++ {
   265  		if !reg.WaitFor16(hw.Timeout, hw.i2sr, I2SR_IIF, 1, 1) {
   266  			return errors.New("timeout on byte reception")
   267  		}
   268  
   269  		if i == size-2 {
   270  			reg.Set16(hw.i2cr, I2CR_TXAK)
   271  		} else if i == size-1 {
   272  			hw.stop()
   273  		}
   274  
   275  		buf[i] = byte(reg.Read16(hw.i2dr) & 0xff)
   276  		reg.Clear16(hw.i2sr, I2SR_IIF)
   277  	}
   278  
   279  	return
   280  }
   281  
   282  func (hw *I2C) tx(buf []byte) (err error) {
   283  	for i := 0; i < len(buf); i++ {
   284  		reg.Clear16(hw.i2sr, I2SR_IIF)
   285  		reg.Write16(hw.i2dr, uint16(buf[i]))
   286  
   287  		if !reg.WaitFor16(hw.Timeout, hw.i2sr, I2SR_IIF, 1, 1) {
   288  			return errors.New("timeout on byte transmission")
   289  		}
   290  
   291  		if reg.Get16(hw.i2sr, I2SR_RXAK, 1) == 1 {
   292  			return errors.New("no acknowledgement received")
   293  		}
   294  	}
   295  
   296  	return
   297  }
   298  
   299  func (hw *I2C) start(repeat bool) (err error) {
   300  	var pos int
   301  
   302  	if repeat == false {
   303  		// wait for bus to be free
   304  		if !reg.WaitFor16(hw.Timeout, hw.i2sr, I2SR_IBB, 1, 0) {
   305  			return errors.New("timeout waiting bus to be free")
   306  		}
   307  
   308  		// enable master mode, generates START signal
   309  		pos = I2CR_MSTA
   310  	} else {
   311  		pos = I2CR_RSTA
   312  	}
   313  
   314  	reg.Set16(hw.i2cr, pos)
   315  
   316  	// wait for bus to be busy
   317  	if !reg.WaitFor16(hw.Timeout, hw.i2sr, I2SR_IBB, 1, 1) {
   318  		reg.Clear16(hw.i2cr, pos)
   319  		return errors.New("timeout waiting bus to be busy")
   320  	}
   321  
   322  	if repeat == false {
   323  		// set Master Transmit mode
   324  		reg.Set16(hw.i2cr, I2CR_MTX)
   325  	}
   326  
   327  	return
   328  }
   329  
   330  func (hw *I2C) stop() {
   331  	reg.Clear16(hw.i2cr, I2CR_MSTA)
   332  	reg.Clear16(hw.i2cr, I2CR_MTX)
   333  }