static u8 wait_9bit(struct tc300k_data *data) { int i; int buf; u8 send_buf = 0; gpio_direction_input(data->pdata->gpio_sda); s3c_gpio_setpull(data->pdata->gpio_sda, S3C_GPIO_PULL_NONE); getsda(data); ndelay(10); setscl(data, 1); ndelay(40); setscl(data, 0); ndelay(20); for (i = 0; i < 8; i++) { setscl(data, 1); ndelay(20); buf = getsda(data); ndelay(20); setscl(data, 0); ndelay(20); send_buf |= (buf & 0x01) << i; } setsda(data, 0); return send_buf; }
/* I2C receiving of bytes - does not send an offset byte */ int efx_i2c_recv_bytes(struct efx_i2c_interface *i2c, u8 device_id, u8 *bytes, unsigned int len) { int i; int rc; EFX_WARN_ON_PARANOID(getsda(i2c) != 1); EFX_WARN_ON_PARANOID(getscl(i2c) != 1); EFX_WARN_ON_PARANOID(len < 1); /* Select device */ i2c_start(i2c); /* Read data from device */ rc = i2c_send_byte(i2c, i2c_read_cmd(device_id)); if (rc) goto out; for (i = 0; i < (len - 1); i++) /* Read and acknowledge all but the last byte */ bytes[i] = i2c_recv_byte(i2c, 1); /* Read last byte with no acknowledgement */ bytes[i] = i2c_recv_byte(i2c, 0); out: i2c_stop(i2c); i2c_release(i2c); return rc; }
/* This performs a fast write of one or more consecutive bytes to an * I2C device. Not all devices support consecutive writes of more * than one byte; for these devices use efx_i2c_write() instead. */ int efx_i2c_fast_write(struct efx_i2c_interface *i2c, u8 device_id, u8 offset, const u8 *data, unsigned int len) { int i; int rc; EFX_WARN_ON_PARANOID(getsda(i2c) != 1); EFX_WARN_ON_PARANOID(getscl(i2c) != 1); EFX_WARN_ON_PARANOID(len < 1); /* Select device and starting offset */ i2c_start(i2c); rc = i2c_send_byte(i2c, i2c_write_cmd(device_id)); if (rc) goto out; rc = i2c_send_byte(i2c, offset); if (rc) goto out; /* Write data to device */ for (i = 0; i < len; i++) { rc = i2c_send_byte(i2c, data[i]); if (rc) goto out; } out: i2c_stop(i2c); i2c_release(i2c); return rc; }
static int i2c_outb(int c) { int i; int ack; /* assert: scl is low */ for (i = 7; i >= 0; i--) { if (c & ( 1 << i )) { sdahi(); } else { sdalo(); } if (sclhi() < 0) { /* timed out */ sdahi(); /* we don't want to block the net */ return -ETIMEDOUT; }; scllo(); } sdahi(); if (sclhi() < 0) { return -ETIMEDOUT; }; /* read ack: SDA should be pulled down by slave */ ack = getsda() == 0; /* ack: sda is pulled low ->success. */ scllo(); if (rtc_debug) printk(KERN_DEBUG "i2c_outb(0x%02x) -> %s\n", c, ack ? "ACK": "NAK"); return ack; /* return 1 if device acked */ /* assert: scl is low (sda undef) */ }
static inline void i2c_release(struct efx_i2c_interface *i2c) { EFX_WARN_ON_PARANOID(!i2c->scl); EFX_WARN_ON_PARANOID(!i2c->sda); /* Devices may time out if operations do not end */ setscl(i2c, 1); setsda(i2c, 1); EFX_BUG_ON_PARANOID(getsda(i2c) != 1); EFX_BUG_ON_PARANOID(getscl(i2c) != 1); }
static inline int i2c_recv_bit(struct efx_i2c_interface *i2c) { int bit; EFX_WARN_ON_PARANOID(i2c->scl != 0); EFX_WARN_ON_PARANOID(!i2c->sda); setscl(i2c, 1); bit = getsda(i2c); setscl(i2c, 0); return bit; }
static inline int read_bit(struct i2c *base) { int bit; setsda(base, 1); // so that we can read from the OC line... delay_quarter_clock(); setscl(base, 1); delay_half_clock(); setscl(base, 0); bit = getsda(base); delay_quarter_clock(); // printf("read bit %d\n", bit); return bit; }
int efx_i2c_check_presence(struct efx_i2c_interface *i2c, u8 device_id) { int rc; /* If someone is driving the bus low we just give up. */ if (getsda(i2c) == 0 || getscl(i2c) == 0) { EFX_ERR(i2c->efx, "%s someone is holding the I2C bus low." " Giving up.\n", __func__); return -EFAULT; } /* Pretend to initiate a device write */ i2c_start(i2c); rc = i2c_send_byte(i2c, i2c_write_cmd(device_id)); if (rc) goto out; out: i2c_stop(i2c); i2c_release(i2c); return rc; }
static int i2c_inb(int ack) { int i; unsigned int indata = 0; /* assert: scl is low */ sdahi(); for (i = 0; i < 8; i++) { if (sclhi() < 0) { return -ETIMEDOUT; }; indata *= 2; if (getsda()) indata |= 0x01; scllo(); } if (ack) { sdalo(); } else { sdahi(); } if (sclhi() < 0) { sdahi(); return -ETIMEDOUT; } scllo(); sdahi(); if (rtc_debug) printk(KERN_DEBUG "i2c_inb() -> 0x%02x\n", indata); /* assert: scl is low */ return indata & 0xff; }