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 }