1/* 2 * Copyright 2007, Axel D��rfler, axeld@pinc-software.de. All Rights Reserved. 3 * Copyright 2003, Thomas Kurschel. All Rights Reserved. 4 * Distributed under the terms of the MIT License. 5 */ 6 7/*! 8 I2C protocol 9*/ 10 11#include "i2c.h" 12 13#include <KernelExport.h> 14#include <OS.h> 15#include <string.h> 16 17 18//#define TRACE_I2C 19#ifdef TRACE_I2C 20#ifdef __cplusplus 21extern "C" 22#endif 23void _sPrintf(const char *format, ...); 24# define TRACE(x...) _sPrintf("I2C: " x) 25#else 26# define TRACE(x...) ; 27#endif 28 29 30/*! 31 I2c timings, rounded up (Philips 1995 i2c bus specification, p20) 32*/ 33 34//! Timing for standard mode i2c (100kHz max) 35const static i2c_timing kTiming100k = { 36 .buf = 5, 37 .hd_sta = 4, 38 .low = 5, 39 .high = 4, 40 .su_sta = 5, 41 .hd_dat = 1, 42 .su_dat = 2, 43 .r = 2, 44 .f = 2, 45 .su_sto = 4, 46 47 // these are unspecified, use half a clock cycle as a safe guess 48 .start_timeout = 5, 49 .byte_timeout = 5, 50 .bit_timeout = 5, 51 .ack_start_timeout = 5, 52 .ack_timeout = 5 53}; 54 55//! Timing for fast mode i2c (400kHz max) 56const static i2c_timing kTiming400k = { 57 .buf = 2, 58 .hd_sta = 1, 59 .low = 2, 60 .high = 1, 61 .su_sta = 1, 62 .hd_dat = 0, 63 .su_dat = 1, 64 .r = 1, 65 .f = 1, 66 .su_sto = 1, 67 68 // these are unspecified, use half a clock cycle as a safe guess 69 .start_timeout = 2, 70 .byte_timeout = 2, 71 .bit_timeout = 2, 72 .ack_start_timeout = 2, 73 .ack_timeout = 2 74}; 75 76 77/*! 78 There's no spin in user space, but we need it to wait a couple 79 of microseconds only 80 (in this case, snooze has much too much overhead) 81*/ 82void 83spin(bigtime_t delay) 84{ 85 bigtime_t startTime = system_time(); 86 87 while (system_time() - startTime < delay) 88 ; 89} 90 91 92//! Wait until slave releases clock signal ("clock stretching") 93static status_t 94wait_for_clk(const i2c_bus *bus, bigtime_t timeout) 95{ 96 bigtime_t startTime; 97 98 // wait for clock signal to raise 99 spin(bus->timing.r); 100 101 startTime = system_time(); 102 103 while (true) { 104 int clk, data; 105 106 bus->get_signals(bus->cookie, &clk, &data); 107 if (clk != 0) 108 return B_OK; 109 110 if (system_time() - startTime > timeout) { 111 TRACE("%s: Timeout waiting on clock (r)\n", __func__); 112 return B_TIMEOUT; 113 } 114 115 spin(bus->timing.r); 116 } 117} 118 119 120//! Send start or repeated start condition 121static status_t 122send_start_condition(const i2c_bus *bus) 123{ 124 status_t status; 125 126 bus->set_signals(bus->cookie, 1, 1); 127 128 status = wait_for_clk(bus, bus->timing.start_timeout); 129 if (status != B_OK) { 130 TRACE("%s: Timeout sending start condition\n", __func__); 131 return status; 132 } 133 134 spin(bus->timing.su_sta); 135 bus->set_signals(bus->cookie, 1, 0); 136 spin(bus->timing.hd_sta); 137 bus->set_signals(bus->cookie, 0, 0); 138 spin(bus->timing.f); 139 140 return B_OK; 141} 142 143 144//! Send stop condition 145static status_t 146send_stop_condition(const i2c_bus *bus) 147{ 148 status_t status; 149 150 bus->set_signals(bus->cookie, 0, 0); 151 spin(bus->timing.r); 152 bus->set_signals(bus->cookie, 1, 0); 153 154 // a slave may wait for us, so let elapse the acknowledge timeout 155 // to make the slave release bus control 156 status = wait_for_clk(bus, bus->timing.ack_timeout); 157 if (status != B_OK) { 158 TRACE("%s: Timeout sending stop condition\n", __func__); 159 return status; 160 } 161 162 spin(bus->timing.su_sto); 163 bus->set_signals(bus->cookie, 1, 1); 164 spin(bus->timing.buf); 165 166 return B_OK; 167} 168 169 170//! Send one bit 171static status_t 172send_bit(const i2c_bus *bus, uint8 bit, int timeout) 173{ 174 status_t status; 175 176 //TRACE("send_bit(bit = %d)\n", bit & 1); 177 178 bus->set_signals(bus->cookie, 0, bit & 1); 179 spin(bus->timing.su_dat); 180 bus->set_signals(bus->cookie, 1, bit & 1); 181 182 status = wait_for_clk(bus, timeout); 183 if (status != B_OK) { 184 TRACE("%s: Timeout when sending next bit\n", __func__); 185 return status; 186 } 187 188 spin(bus->timing.high); 189 bus->set_signals(bus->cookie, 0, bit & 1); 190 spin(bus->timing.f + bus->timing.low); 191 192 return B_OK; 193} 194 195 196//! Send acknowledge and wait for reply 197static status_t 198send_acknowledge(const i2c_bus *bus) 199{ 200 status_t status; 201 bigtime_t startTime; 202 203 // release data so slave can modify it 204 bus->set_signals(bus->cookie, 0, 1); 205 spin(bus->timing.su_dat); 206 bus->set_signals(bus->cookie, 1, 1); 207 208 status = wait_for_clk(bus, bus->timing.ack_start_timeout); 209 if (status != B_OK) { 210 TRACE("%s: Timeout when sending acknowledge\n", __func__); 211 return status; 212 } 213 214 // data and clock is high, now wait for slave to pull data low 215 // (according to spec, this can happen any time once clock is high) 216 startTime = system_time(); 217 218 while (true) { 219 int clk, data; 220 221 bus->get_signals(bus->cookie, &clk, &data); 222 223 if (data == 0) 224 break; 225 226 if (system_time() - startTime > bus->timing.ack_timeout) { 227 TRACE("%s: slave didn't acknowledge byte within ack_timeout: %ld\n", 228 __func__, bus->timing.ack_timeout); 229 return B_TIMEOUT; 230 } 231 232 spin(bus->timing.r); 233 } 234 235 TRACE("send_acknowledge(): Success!\n"); 236 237 // make sure we've waited at least t_high 238 spin(bus->timing.high); 239 240 bus->set_signals(bus->cookie, 0, 1); 241 spin(bus->timing.f + bus->timing.low); 242 243 return B_OK; 244} 245 246 247//! Send byte and wait for acknowledge if <ackowledge> is true 248static status_t 249send_byte(const i2c_bus *bus, uint8 byte, bool acknowledge) 250{ 251 int i; 252 253 //TRACE("%s: (byte = %x)\n", __func__, byte); 254 255 for (i = 7; i >= 0; --i) { 256 status_t status = send_bit(bus, byte >> i, 257 i == 7 ? bus->timing.byte_timeout : bus->timing.bit_timeout); 258 if (status != B_OK) 259 return status; 260 } 261 262 if (acknowledge) 263 return send_acknowledge(bus); 264 265 return B_OK; 266} 267 268 269//! Send slave address, obeying 10-bit addresses and general call addresses 270static status_t 271send_slave_address(const i2c_bus *bus, uint8 slaveAddress, bool isWrite) 272{ 273 status_t status; 274 275 TRACE("%s: 0x%X\n", __func__, slaveAddress); 276 status = send_byte(bus, (slaveAddress & 0xfe) | (isWrite ? 0 : 1), true); 277 if (status != B_OK) 278 return status; 279 280 // there are the following special cases if the first byte looks like: 281 // - 0000 0000 - general call address (second byte with address follows) 282 // - 0000 0001 - start byte 283 // - 0000 001x - CBus address 284 // - 0000 010x - address reserved for different bus format 285 // - 0000 011x | 286 // - 0000 1xxx |-> reserved 287 // - 1111 1xxx | 288 // - 1111 0xxx - 10 bit address (second byte contains remaining 8 bits) 289 290 // the lsb is 0 for write and 1 for read (except for general call address) 291 if ((slaveAddress & 0xff) != 0 && (slaveAddress & 0xf8) != 0xf0) 292 return B_OK; 293 294 return send_byte(bus, slaveAddress >> 8, true); 295 // send second byte if required 296} 297 298 299//! Receive one bit 300static status_t 301receive_bit(const i2c_bus *bus, bool *bit, int timeout) 302{ 303 status_t status; 304 int clk, data; 305 306 bus->set_signals(bus->cookie, 1, 1); 307 // release clock 308 309 // wait for slave to raise clock 310 status = wait_for_clk(bus, timeout); 311 if (status != B_OK) { 312 TRACE("%s: Timeout waiting for bit sent by slave\n", __func__); 313 return status; 314 } 315 316 bus->get_signals(bus->cookie, &clk, &data); 317 // sample data 318 319 spin(bus->timing.high); 320 // leave clock high for minimal time 321 322 bus->set_signals(bus->cookie, 0, 1); 323 // pull clock low so slave waits for us before next bit 324 325 spin(bus->timing.f + bus->timing.low); 326 // let it settle and leave it low for minimal time 327 // to make sure slave has finished bit transmission too 328 329 *bit = data; 330 return B_OK; 331} 332 333 334/*! 335 Send positive acknowledge afterwards if <acknowledge> is true, 336 else send negative one 337*/ 338static status_t 339receive_byte(const i2c_bus *bus, uint8 *resultByte, bool acknowledge) 340{ 341 uint8 byte = 0; 342 int i; 343 344 // pull clock low to let slave wait for us 345 bus->set_signals(bus->cookie, 0, 1); 346 347 for (i = 7; i >= 0; i--) { 348 bool bit; 349 350 status_t status = receive_bit(bus, &bit, 351 i == 7 ? bus->timing.byte_timeout : bus->timing.bit_timeout); 352 if (status != B_OK) 353 return status; 354 355 byte = (byte << 1) | bit; 356 } 357 358 //SHOW_FLOW(3, "%x ", byte); 359 360 *resultByte = byte; 361 362 return send_bit(bus, acknowledge ? 0 : 1, bus->timing.bit_timeout); 363} 364 365 366//! Send multiple bytes 367static status_t 368send_bytes(const i2c_bus *bus, const uint8 *writeBuffer, ssize_t writeLength) 369{ 370 TRACE("%s: (length = %ld)\n", __func__, writeLength); 371 372 for (; writeLength > 0; --writeLength, ++writeBuffer) { 373 status_t status = send_byte(bus, *writeBuffer, true); 374 if (status != B_OK) 375 return status; 376 } 377 378 return B_OK; 379} 380 381 382//! Receive multiple bytes 383static status_t 384receive_bytes(const i2c_bus *bus, uint8 *readBuffer, ssize_t readLength) 385{ 386 TRACE("%s: (length = %ld)\n", __func__, readLength); 387 388 for (; readLength > 0; --readLength, ++readBuffer) { 389 status_t status = receive_byte(bus, readBuffer, readLength > 1); 390 if (status != B_OK) 391 return status; 392 } 393 394 return B_OK; 395} 396 397 398// #pragma mark - exported functions 399 400 401//! Combined i2c send+receive format 402status_t 403i2c_send_receive_callback(const i2c_bus *bus, uint32 slaveAddress, const uint8 *writeBuffer, 404 size_t writeLength, uint8 *readBuffer, size_t readLength) 405{ 406 status_t status; 407 408 // the address is 7-bit 409 slaveAddress <<= 1; 410 if (slaveAddress > 0xff) 411 return B_BAD_VALUE; 412 413 status = send_start_condition(bus); 414 if (status != B_OK) 415 return status; 416 417 status = send_slave_address(bus, slaveAddress, true); 418 if (status != B_OK) 419 goto err; 420 421 status = send_bytes(bus, writeBuffer, writeLength); 422 if (status != B_OK) 423 goto err; 424 425 status = send_start_condition(bus); 426 if (status != B_OK) 427 return status; 428 429 status = send_slave_address(bus, slaveAddress, false); 430 if (status != B_OK) 431 goto err; 432 433 status = receive_bytes(bus, readBuffer, readLength); 434 if (status != B_OK) 435 goto err; 436 437 return send_stop_condition(bus); 438 439err: 440 TRACE("%s: Cancelling transmission\n", __func__); 441 send_stop_condition(bus); 442 return status; 443} 444 445 446void 447i2c_get100k_timing(i2c_timing *timing) 448{ 449 // AKA standard i2c mode 450 memcpy(timing, &kTiming100k, sizeof(i2c_timing)); 451} 452 453 454void 455i2c_get400k_timing(i2c_timing *timing) 456{ 457 // AKA fast i2c mode 458 memcpy(timing, &kTiming400k, sizeof(i2c_timing)); 459} 460