123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381 |
- /****************************************************************************
- * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2005 Fen Systems Ltd.
- * Copyright 2006-2008 Solarflare Communications Inc.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published
- * by the Free Software Foundation, incorporated herein by reference.
- */
- #include <linux/delay.h>
- #include "net_driver.h"
- #include "i2c-direct.h"
- /*
- * I2C data (SDA) and clock (SCL) line read/writes with appropriate
- * delays.
- */
- static inline void setsda(struct efx_i2c_interface *i2c, int state)
- {
- udelay(i2c->op->udelay);
- i2c->sda = state;
- i2c->op->setsda(i2c);
- udelay(i2c->op->udelay);
- }
- static inline void setscl(struct efx_i2c_interface *i2c, int state)
- {
- udelay(i2c->op->udelay);
- i2c->scl = state;
- i2c->op->setscl(i2c);
- udelay(i2c->op->udelay);
- }
- static inline int getsda(struct efx_i2c_interface *i2c)
- {
- int sda;
- udelay(i2c->op->udelay);
- sda = i2c->op->getsda(i2c);
- udelay(i2c->op->udelay);
- return sda;
- }
- static inline int getscl(struct efx_i2c_interface *i2c)
- {
- int scl;
- udelay(i2c->op->udelay);
- scl = i2c->op->getscl(i2c);
- udelay(i2c->op->udelay);
- return scl;
- }
- /*
- * I2C low-level protocol operations
- *
- */
- 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 void i2c_start(struct efx_i2c_interface *i2c)
- {
- /* We may be restarting immediately after a {send,recv}_bit,
- * so SCL will not necessarily already be high.
- */
- EFX_WARN_ON_PARANOID(!i2c->sda);
- setscl(i2c, 1);
- setsda(i2c, 0);
- setscl(i2c, 0);
- setsda(i2c, 1);
- }
- static inline void i2c_send_bit(struct efx_i2c_interface *i2c, int bit)
- {
- EFX_WARN_ON_PARANOID(i2c->scl != 0);
- setsda(i2c, bit);
- setscl(i2c, 1);
- setscl(i2c, 0);
- setsda(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 void i2c_stop(struct efx_i2c_interface *i2c)
- {
- EFX_WARN_ON_PARANOID(i2c->scl != 0);
- setsda(i2c, 0);
- setscl(i2c, 1);
- setsda(i2c, 1);
- }
- /*
- * I2C mid-level protocol operations
- *
- */
- /* Sends a byte via the I2C bus and checks for an acknowledgement from
- * the slave device.
- */
- static int i2c_send_byte(struct efx_i2c_interface *i2c, u8 byte)
- {
- int i;
- /* Send byte */
- for (i = 0; i < 8; i++) {
- i2c_send_bit(i2c, !!(byte & 0x80));
- byte <<= 1;
- }
- /* Check for acknowledgement from slave */
- return (i2c_recv_bit(i2c) == 0 ? 0 : -EIO);
- }
- /* Receives a byte via the I2C bus and sends ACK/NACK to the slave device. */
- static u8 i2c_recv_byte(struct efx_i2c_interface *i2c, int ack)
- {
- u8 value = 0;
- int i;
- /* Receive byte */
- for (i = 0; i < 8; i++)
- value = (value << 1) | i2c_recv_bit(i2c);
- /* Send ACK/NACK */
- i2c_send_bit(i2c, (ack ? 0 : 1));
- return value;
- }
- /* Calculate command byte for a read operation */
- static inline u8 i2c_read_cmd(u8 device_id)
- {
- return ((device_id << 1) | 1);
- }
- /* Calculate command byte for a write operation */
- static inline u8 i2c_write_cmd(u8 device_id)
- {
- return ((device_id << 1) | 0);
- }
- 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;
- }
- /* This performs a fast read of one or more consecutive bytes from an
- * I2C device. Not all devices support consecutive reads of more than
- * one byte; for these devices use efx_i2c_read() instead.
- */
- int efx_i2c_fast_read(struct efx_i2c_interface *i2c,
- u8 device_id, u8 offset, 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(data == NULL);
- 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;
- /* Read data from device */
- i2c_start(i2c);
- 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 */
- data[i] = i2c_recv_byte(i2c, 1);
- /* Read last byte with no acknowledgement */
- data[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;
- }
- /* I2C byte-by-byte read */
- int efx_i2c_read(struct efx_i2c_interface *i2c,
- u8 device_id, u8 offset, u8 *data, unsigned int len)
- {
- int rc;
- /* i2c_fast_read with length 1 is a single byte read */
- for (; len > 0; offset++, data++, len--) {
- rc = efx_i2c_fast_read(i2c, device_id, offset, data, 1);
- if (rc)
- return rc;
- }
- return 0;
- }
- /* I2C byte-by-byte write */
- int efx_i2c_write(struct efx_i2c_interface *i2c,
- u8 device_id, u8 offset, const u8 *data, unsigned int len)
- {
- int rc;
- /* i2c_fast_write with length 1 is a single byte write */
- for (; len > 0; offset++, data++, len--) {
- rc = efx_i2c_fast_write(i2c, device_id, offset, data, 1);
- if (rc)
- return rc;
- mdelay(i2c->op->mdelay);
- }
- return 0;
- }
- /* This is just a slightly neater wrapper round efx_i2c_fast_write
- * in the case where the target doesn't take an offset
- */
- int efx_i2c_send_bytes(struct efx_i2c_interface *i2c,
- u8 device_id, const u8 *data, unsigned int len)
- {
- return efx_i2c_fast_write(i2c, device_id, data[0], data + 1, len - 1);
- }
- /* 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;
- }
- /* SMBus and some I2C devices will time out if the I2C clock is
- * held low for too long. This is most likely to happen in virtualised
- * systems (when the entire domain is descheduled) but could in
- * principle happen due to preemption on any busy system (and given the
- * potential length of an I2C operation turning preemption off is not
- * a sensible option). The following functions deal with the failure by
- * retrying up to a fixed number of times.
- */
- #define I2C_MAX_RETRIES (10)
- /* The timeout problem will result in -EIO. If the wrapped function
- * returns any other error, pass this up and do not retry. */
- #define RETRY_WRAPPER(_f) \
- int retries = I2C_MAX_RETRIES; \
- int rc; \
- while (retries) { \
- rc = _f; \
- if (rc != -EIO) \
- return rc; \
- retries--; \
- } \
- return rc; \
- int efx_i2c_check_presence_retry(struct efx_i2c_interface *i2c, u8 device_id)
- {
- RETRY_WRAPPER(efx_i2c_check_presence(i2c, device_id))
- }
- int efx_i2c_read_retry(struct efx_i2c_interface *i2c,
- u8 device_id, u8 offset, u8 *data, unsigned int len)
- {
- RETRY_WRAPPER(efx_i2c_read(i2c, device_id, offset, data, len))
- }
- int efx_i2c_write_retry(struct efx_i2c_interface *i2c,
- u8 device_id, u8 offset, const u8 *data, unsigned int len)
- {
- RETRY_WRAPPER(efx_i2c_write(i2c, device_id, offset, data, len))
- }
|