diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/i2c/i2c-gpio.c | 133 | 
1 files changed, 64 insertions, 69 deletions
| diff --git a/drivers/i2c/i2c-gpio.c b/drivers/i2c/i2c-gpio.c index d56540b4621..e3a21ad3b29 100644 --- a/drivers/i2c/i2c-gpio.c +++ b/drivers/i2c/i2c-gpio.c @@ -32,23 +32,32 @@ struct i2c_gpio_bus {  	int udelay;  	 /* sda, scl */  	struct gpio_desc gpios[PIN_COUNT]; + +	int (*get_sda)(struct i2c_gpio_bus *bus); +	void (*set_sda)(struct i2c_gpio_bus *bus, int bit); +	void (*set_scl)(struct i2c_gpio_bus *bus, int bit);  }; -static int i2c_gpio_sda_get(struct gpio_desc *sda) +static int i2c_gpio_sda_get(struct i2c_gpio_bus *bus)  { +	struct gpio_desc *sda = &bus->gpios[PIN_SDA]; +  	return dm_gpio_get_value(sda);  } -static void i2c_gpio_sda_set(struct gpio_desc *sda, int bit) +static void i2c_gpio_sda_set(struct i2c_gpio_bus *bus, int bit)  { +	struct gpio_desc *sda = &bus->gpios[PIN_SDA]; +  	if (bit)  		dm_gpio_set_dir_flags(sda, GPIOD_IS_IN);  	else  		dm_gpio_set_dir_flags(sda, GPIOD_IS_OUT);  } -static void i2c_gpio_scl_set(struct gpio_desc *scl, int bit) +static void i2c_gpio_scl_set(struct i2c_gpio_bus *bus, int bit)  { +	struct gpio_desc *scl = &bus->gpios[PIN_SCL];  	ulong flags = GPIOD_IS_OUT;  	if (bit) @@ -56,65 +65,60 @@ static void i2c_gpio_scl_set(struct gpio_desc *scl, int bit)  	dm_gpio_set_dir_flags(scl, flags);  } -static void i2c_gpio_write_bit(struct gpio_desc *scl, struct gpio_desc *sda, -			       int delay, uchar bit) +static void i2c_gpio_write_bit(struct i2c_gpio_bus *bus, int delay, uchar bit)  { -	i2c_gpio_scl_set(scl, 0); +	bus->set_scl(bus, 0);  	udelay(delay); -	i2c_gpio_sda_set(sda, bit); +	bus->set_sda(bus, bit);  	udelay(delay); -	i2c_gpio_scl_set(scl, 1); +	bus->set_scl(bus, 1);  	udelay(2 * delay);  } -static int i2c_gpio_read_bit(struct gpio_desc *scl, struct gpio_desc *sda, -			     int delay) +static int i2c_gpio_read_bit(struct i2c_gpio_bus *bus, int delay)  {  	int value; -	i2c_gpio_scl_set(scl, 1); +	bus->set_scl(bus, 1);  	udelay(delay); -	value = i2c_gpio_sda_get(sda); +	value = bus->get_sda(bus);  	udelay(delay); -	i2c_gpio_scl_set(scl, 0); +	bus->set_scl(bus, 0);  	udelay(2 * delay);  	return value;  }  /* START: High -> Low on SDA while SCL is High */ -static void i2c_gpio_send_start(struct gpio_desc *scl, struct gpio_desc *sda, -				int delay) +static void i2c_gpio_send_start(struct i2c_gpio_bus *bus, int delay)  {  	udelay(delay); -	i2c_gpio_sda_set(sda, 1); +	bus->set_sda(bus, 1);  	udelay(delay); -	i2c_gpio_scl_set(scl, 1); +	bus->set_scl(bus, 1);  	udelay(delay); -	i2c_gpio_sda_set(sda, 0); +	bus->set_sda(bus, 0);  	udelay(delay);  }  /* STOP: Low -> High on SDA while SCL is High */ -static void i2c_gpio_send_stop(struct gpio_desc *scl, struct gpio_desc *sda, -			       int delay) +static void i2c_gpio_send_stop(struct i2c_gpio_bus *bus, int delay)  { -	i2c_gpio_scl_set(scl, 0); +	bus->set_scl(bus, 0);  	udelay(delay); -	i2c_gpio_sda_set(sda, 0); +	bus->set_sda(bus, 0);  	udelay(delay); -	i2c_gpio_scl_set(scl, 1); +	bus->set_scl(bus, 1);  	udelay(delay); -	i2c_gpio_sda_set(sda, 1); +	bus->set_sda(bus, 1);  	udelay(delay);  }  /* ack should be I2C_ACK or I2C_NOACK */ -static void i2c_gpio_send_ack(struct gpio_desc *scl, struct gpio_desc *sda, -			      int delay, int ack) +static void i2c_gpio_send_ack(struct i2c_gpio_bus *bus, int delay, int ack)  { -	i2c_gpio_write_bit(scl, sda, delay, ack); -	i2c_gpio_scl_set(scl, 0); +	i2c_gpio_write_bit(bus, delay, ack); +	bus->set_scl(bus, 0);  	udelay(delay);  } @@ -123,44 +127,41 @@ static void i2c_gpio_send_ack(struct gpio_desc *scl, struct gpio_desc *sda,   * to clock any confused device back into an idle state.  Also send a   * <stop> at the end of the sequence for belts & suspenders.   */ -static void i2c_gpio_send_reset(struct gpio_desc *scl, struct gpio_desc *sda, -				int delay) +static void i2c_gpio_send_reset(struct i2c_gpio_bus *bus, int delay)  {  	int j;  	for (j = 0; j < 9; j++) -		i2c_gpio_write_bit(scl, sda, delay, 1); +		i2c_gpio_write_bit(bus, delay, 1); -	i2c_gpio_send_stop(scl, sda, delay); +	i2c_gpio_send_stop(bus, delay);  }  /* Set sda high with low clock, before reading slave data */ -static void i2c_gpio_sda_high(struct gpio_desc *scl, struct gpio_desc *sda, -			      int delay) +static void i2c_gpio_sda_high(struct i2c_gpio_bus *bus, int delay)  { -	i2c_gpio_scl_set(scl, 0); +	bus->set_scl(bus, 0);  	udelay(delay); -	i2c_gpio_sda_set(sda, 1); +	bus->set_sda(bus, 1);  	udelay(delay);  }  /* Send 8 bits and look for an acknowledgement */ -static int i2c_gpio_write_byte(struct gpio_desc *scl, struct gpio_desc *sda, -			       int delay, uchar data) +static int i2c_gpio_write_byte(struct i2c_gpio_bus *bus, int delay, uchar data)  {  	int j;  	int nack;  	for (j = 0; j < 8; j++) { -		i2c_gpio_write_bit(scl, sda, delay, data & 0x80); +		i2c_gpio_write_bit(bus, delay, data & 0x80);  		data <<= 1;  	}  	udelay(delay);  	/* Look for an <ACK>(negative logic) and return it */ -	i2c_gpio_sda_high(scl, sda, delay); -	nack = i2c_gpio_read_bit(scl, sda, delay); +	i2c_gpio_sda_high(bus, delay); +	nack = i2c_gpio_read_bit(bus, delay);  	return nack;	/* not a nack is an ack */  } @@ -169,31 +170,29 @@ static int i2c_gpio_write_byte(struct gpio_desc *scl, struct gpio_desc *sda,   * if ack == I2C_ACK, ACK the byte so can continue reading, else   * send I2C_NOACK to end the read.   */ -static uchar i2c_gpio_read_byte(struct gpio_desc *scl, struct gpio_desc *sda, -				int delay, int ack) +static uchar i2c_gpio_read_byte(struct i2c_gpio_bus *bus, int delay, int ack)  {  	int  data;  	int  j; -	i2c_gpio_sda_high(scl, sda, delay); +	i2c_gpio_sda_high(bus, delay);  	data = 0;  	for (j = 0; j < 8; j++) {  		data <<= 1; -		data |= i2c_gpio_read_bit(scl, sda, delay); +		data |= i2c_gpio_read_bit(bus, delay);  	} -	i2c_gpio_send_ack(scl, sda, delay, ack); +	i2c_gpio_send_ack(bus, delay, ack);  	return data;  }  /* send start and the slave chip address */ -int i2c_send_slave_addr(struct gpio_desc *scl, struct gpio_desc *sda, int delay, -			uchar chip) +int i2c_send_slave_addr(struct i2c_gpio_bus *bus, int delay, uchar chip)  { -	i2c_gpio_send_start(scl, sda, delay); +	i2c_gpio_send_start(bus, delay); -	if (i2c_gpio_write_byte(scl, sda, delay, chip)) { -		i2c_gpio_send_stop(scl, sda, delay); +	if (i2c_gpio_write_byte(bus, delay, chip)) { +		i2c_gpio_send_stop(bus, delay);  		return -EIO;  	} @@ -204,29 +203,27 @@ static int i2c_gpio_write_data(struct i2c_gpio_bus *bus, uchar chip,  			       uchar *buffer, int len,  			       bool end_with_repeated_start)  { -	struct gpio_desc *scl = &bus->gpios[PIN_SCL]; -	struct gpio_desc *sda = &bus->gpios[PIN_SDA];  	unsigned int delay = bus->udelay;  	int failures = 0;  	debug("%s: chip %x buffer %p len %d\n", __func__, chip, buffer, len); -	if (i2c_send_slave_addr(scl, sda, delay, chip << 1)) { +	if (i2c_send_slave_addr(bus, delay, chip << 1)) {  		debug("i2c_write, no chip responded %02X\n", chip);  		return -EIO;  	}  	while (len-- > 0) { -		if (i2c_gpio_write_byte(scl, sda, delay, *buffer++)) +		if (i2c_gpio_write_byte(bus, delay, *buffer++))  			failures++;  	}  	if (!end_with_repeated_start) { -		i2c_gpio_send_stop(scl, sda, delay); +		i2c_gpio_send_stop(bus, delay);  		return failures;  	} -	if (i2c_send_slave_addr(scl, sda, delay, (chip << 1) | 0x1)) { +	if (i2c_send_slave_addr(bus, delay, (chip << 1) | 0x1)) {  		debug("i2c_write, no chip responded %02X\n", chip);  		return -EIO;  	} @@ -237,16 +234,14 @@ static int i2c_gpio_write_data(struct i2c_gpio_bus *bus, uchar chip,  static int i2c_gpio_read_data(struct i2c_gpio_bus *bus, uchar chip,  			      uchar *buffer, int len)  { -	struct gpio_desc *scl = &bus->gpios[PIN_SCL]; -	struct gpio_desc *sda = &bus->gpios[PIN_SDA];  	unsigned int delay = bus->udelay;  	debug("%s: chip %x buffer: %p len %d\n", __func__, chip, buffer, len);  	while (len-- > 0) -		*buffer++ = i2c_gpio_read_byte(scl, sda, delay, len == 0); +		*buffer++ = i2c_gpio_read_byte(bus, delay, len == 0); -	i2c_gpio_send_stop(scl, sda, delay); +	i2c_gpio_send_stop(bus, delay);  	return 0;  } @@ -277,14 +272,12 @@ static int i2c_gpio_xfer(struct udevice *dev, struct i2c_msg *msg, int nmsgs)  static int i2c_gpio_probe(struct udevice *dev, uint chip, uint chip_flags)  {  	struct i2c_gpio_bus *bus = dev_get_priv(dev); -	struct gpio_desc *scl = &bus->gpios[PIN_SCL]; -	struct gpio_desc *sda = &bus->gpios[PIN_SDA];  	unsigned int delay = bus->udelay;  	int ret; -	i2c_gpio_send_start(scl, sda, delay); -	ret = i2c_gpio_write_byte(scl, sda, delay, (chip << 1) | 0); -	i2c_gpio_send_stop(scl, sda, delay); +	i2c_gpio_send_start(bus, delay); +	ret = i2c_gpio_write_byte(bus, delay, (chip << 1) | 0); +	i2c_gpio_send_stop(bus, delay);  	debug("%s: bus: %d (%s) chip: %x flags: %x ret: %d\n",  	      __func__, dev->seq, dev->name, chip, chip_flags, ret); @@ -295,12 +288,10 @@ static int i2c_gpio_probe(struct udevice *dev, uint chip, uint chip_flags)  static int i2c_gpio_set_bus_speed(struct udevice *dev, unsigned int speed_hz)  {  	struct i2c_gpio_bus *bus = dev_get_priv(dev); -	struct gpio_desc *scl = &bus->gpios[PIN_SCL]; -	struct gpio_desc *sda = &bus->gpios[PIN_SDA];  	bus->udelay = 1000000 / (speed_hz << 2); -	i2c_gpio_send_reset(scl, sda, bus->udelay); +	i2c_gpio_send_reset(bus, bus->udelay);  	return 0;  } @@ -335,6 +326,10 @@ static int i2c_gpio_ofdata_to_platdata(struct udevice *dev)  	bus->udelay = fdtdec_get_int(blob, node, "i2c-gpio,delay-us",  				     DEFAULT_UDELAY); +	bus->get_sda = i2c_gpio_sda_get; +	bus->set_sda = i2c_gpio_sda_set; +	bus->set_scl = i2c_gpio_scl_set; +  	return 0;  error:  	pr_err("Can't get %s gpios! Error: %d", dev->name, ret); | 
