Browse Source

[i2c] Generalise i2c bit-bashing support to addressless devices

Some devices (e.g. the Atmel AT24C11) have no concept of a device
address; they respond to every device address and use this value as
the word address.  Some other devices use part of the device address
field to extend the word address field.

Generalise the i2c bit-bashing support to handle this by defining the
device address length and word address length as properties of an i2c
device.  The word address is assumed to overflow into the device
address field if the address used exceeds the width of the word
address field.

Also add a bus reset mechanism.  i2c chips don't usually have a reset
line, so rebooting the host will not clear any bizarre state that the
chip may be in.  We reset the bus by clocking SCL until we see SDA
high, at which point we know we can generate a start condition and
have it seen by all devices.  We then generate a stop condition to
leave the bus in a known state prior to use.

Finally, add some extra debugging messages to i2c_bit.c.
tags/v0.9.6
Michael Brown 15 years ago
parent
commit
9dccbc0af2
3 changed files with 174 additions and 47 deletions
  1. 108
    39
      src/drivers/bitbash/i2c_bit.c
  2. 3
    3
      src/drivers/net/etherfabric.c
  3. 63
    5
      src/include/gpxe/i2c.h

+ 108
- 39
src/drivers/bitbash/i2c_bit.c View File

@@ -19,6 +19,7 @@
19 19
 #include <stddef.h>
20 20
 #include <stdint.h>
21 21
 #include <errno.h>
22
+#include <string.h>
22 23
 #include <assert.h>
23 24
 #include <unistd.h>
24 25
 #include <gpxe/bitbash.h>
@@ -49,6 +50,7 @@ static void i2c_delay ( void ) {
49 50
  * @v state		New state of SCL
50 51
  */
51 52
 static void setscl ( struct bit_basher *basher, int state ) {
53
+	DBG2 ( "%c", ( state ? '/' : '\\' ) );
52 54
 	write_bit ( basher, I2C_BIT_SCL, state );
53 55
 	i2c_delay();
54 56
 }
@@ -60,6 +62,7 @@ static void setscl ( struct bit_basher *basher, int state ) {
60 62
  * @v state		New state of SDA
61 63
  */
62 64
 static void setsda ( struct bit_basher *basher, int state ) {
65
+	DBG2 ( "%c", ( state ? '1' : '0' ) );
63 66
 	write_bit ( basher, I2C_BIT_SDA, state );
64 67
 	i2c_delay();
65 68
 }
@@ -71,7 +74,10 @@ static void setsda ( struct bit_basher *basher, int state ) {
71 74
  * @ret state		State of SDA
72 75
  */
73 76
 static int getsda ( struct bit_basher *basher ) {
74
-	return read_bit ( basher, I2C_BIT_SDA );
77
+	int state;
78
+	state = read_bit ( basher, I2C_BIT_SDA );
79
+	DBG2 ( "%c", ( state ? '+' : '-' ) );
80
+	return state;
75 81
 }
76 82
 
77 83
 /**
@@ -137,15 +143,20 @@ static void i2c_stop ( struct bit_basher *basher ) {
137 143
  */
138 144
 static int i2c_send_byte ( struct bit_basher *basher, uint8_t byte ) {
139 145
 	int i;
140
-	
146
+	int ack;
147
+
141 148
 	/* Send byte */
149
+	DBG2 ( "[send %02x]", byte );
142 150
 	for ( i = 8 ; i ; i-- ) {
143 151
 		i2c_send_bit ( basher, byte & 0x80 );
144 152
 		byte <<= 1;
145 153
 	}
146 154
 
147 155
 	/* Check for acknowledgement from slave */
148
-	return ( i2c_recv_bit ( basher ) == 0 ? 0 : -EIO );
156
+	ack = ( i2c_recv_bit ( basher ) == 0 );
157
+	DBG2 ( "%s", ( ack ? "[acked]" : "[not acked]" ) );
158
+
159
+	return ( ack ? 0 : -EIO );
149 160
 }
150 161
 
151 162
 /**
@@ -157,19 +168,20 @@ static int i2c_send_byte ( struct bit_basher *basher, uint8_t byte ) {
157 168
  * Receives a byte via the I2C bus and sends NACK to the slave device.
158 169
  */
159 170
 static uint8_t i2c_recv_byte ( struct bit_basher *basher ) {
160
-	uint8_t value = 0;
171
+	uint8_t byte = 0;
161 172
 	int i;
162 173
 
163 174
 	/* Receive byte */
164 175
 	for ( i = 8 ; i ; i-- ) {
165
-		value <<= 1;
166
-		value |= ( i2c_recv_bit ( basher ) & 0x1 );
176
+		byte <<= 1;
177
+		byte |= ( i2c_recv_bit ( basher ) & 0x1 );
167 178
 	}
168 179
 
169 180
 	/* Send NACK */
170 181
 	i2c_send_bit ( basher, 1 );
171 182
 
172
-	return value;
183
+	DBG2 ( "[rcvd %02x]", byte );
184
+	return byte;
173 185
 }
174 186
 
175 187
 /**
@@ -177,36 +189,75 @@ static uint8_t i2c_recv_byte ( struct bit_basher *basher ) {
177 189
  *
178 190
  * @v basher		Bit-bashing interface
179 191
  * @v i2cdev		I2C device
192
+ * @v offset		Starting offset within the device
180 193
  * @v direction		I2C_READ or I2C_WRITE
181 194
  * @ret rc		Return status code
182 195
  */
183 196
 static int i2c_select ( struct bit_basher *basher, struct i2c_device *i2cdev,
184
-			unsigned int direction ) {
197
+			unsigned int offset, unsigned int direction ) {
185 198
 	unsigned int address;
199
+	int shift;
200
+	unsigned int byte;
186 201
 	int rc;
187 202
 
188 203
 	i2c_start ( basher );
189 204
 
190
-	/* First byte of the address */
191
-	address = i2cdev->address;
192
-	if ( i2cdev->tenbit ) {
193
-		address |= I2C_TENBIT_ADDRESS;
194
-		address >>= 8;
195
-	}
196
-	if ( ( rc = i2c_send_byte ( basher, 
197
-				    ( ( address << 1 ) | direction ) ) ) != 0 )
198
-		return rc;
205
+	/* Calculate address to appear on bus */
206
+	address = ( ( ( i2cdev->dev_addr |
207
+			( offset >> ( 8 * i2cdev->word_addr_len ) ) ) << 1 )
208
+		    | direction );
199 209
 
200
-	/* Second byte of the address (10-bit addresses only) */
201
-	if ( i2cdev->tenbit ) {
202
-		if ( ( rc = i2c_send_byte ( basher,
203
-					    ( i2cdev->address & 0xff ) ) ) !=0)
210
+	/* Send address a byte at a time */
211
+	for ( shift = ( 8 * ( i2cdev->dev_addr_len - 1 ) ) ;
212
+	      shift >= 0 ; shift -= 8 ) {
213
+		byte = ( ( address >> shift ) & 0xff );
214
+		if ( ( rc = i2c_send_byte ( basher, byte ) ) != 0 )
204 215
 			return rc;
205 216
 	}
206 217
 
207 218
 	return 0;
208 219
 }
209 220
 
221
+/**
222
+ * Reset I2C bus
223
+ *
224
+ * @v basher		Bit-bashing interface
225
+ * @ret rc		Return status code
226
+ *
227
+ * i2c devices often don't have a reset line, so even a reboot or
228
+ * system power cycle is sometimes not enough to bring them back to a
229
+ * known state.
230
+ */
231
+static int i2c_reset ( struct bit_basher *basher ) {
232
+	unsigned int i;
233
+	int sda;
234
+
235
+	/* Clock through several cycles, waiting for an opportunity to
236
+	 * pull SDA low while SCL is high (which creates a start
237
+	 * condition).
238
+	 */
239
+	setscl ( basher, 0 );
240
+	setsda ( basher, 1 );
241
+	for ( i = 0 ; i < I2C_RESET_MAX_CYCLES ; i++ ) {
242
+		setscl ( basher, 1 );
243
+		sda = getsda ( basher );
244
+		if ( sda ) {
245
+			/* Now that the device will see a start, issue it */
246
+			i2c_start ( basher );
247
+			/* Stop the bus to leave it in a known good state */
248
+			i2c_stop ( basher );
249
+			DBGC ( basher, "I2CBIT %p reset after %d attempts\n",
250
+			       basher, ( i + 1 ) );
251
+			return 0;
252
+		}
253
+		setscl ( basher, 0 );
254
+	}
255
+
256
+	DBGC ( basher, "I2CBIT %p could not reset after %d attempts\n",
257
+	       basher, i );
258
+	return -ETIMEDOUT;
259
+}
260
+
210 261
 /**
211 262
  * Read data from I2C device via bit-bashing interface
212 263
  *
@@ -228,12 +279,14 @@ static int i2c_bit_read ( struct i2c_interface *i2c,
228 279
 	struct bit_basher *basher = &i2cbit->basher;
229 280
 	int rc = 0;
230 281
 
231
-	DBG ( "Reading from I2C device %x: ", i2cdev->address );
282
+	DBGC ( basher, "I2CBIT %p reading from device %x: ",
283
+	       basher, i2cdev->dev_addr );
232 284
 
233
-	while ( 1 ) {
285
+	for ( ; ; data++, offset++ ) {
234 286
 
235 287
 		/* Select device for writing */
236
-		if ( ( rc = i2c_select ( basher, i2cdev, I2C_WRITE ) ) != 0 )
288
+		if ( ( rc = i2c_select ( basher, i2cdev, offset,
289
+					 I2C_WRITE ) ) != 0 )
237 290
 			break;
238 291
 
239 292
 		/* Abort at end of data */
@@ -241,19 +294,20 @@ static int i2c_bit_read ( struct i2c_interface *i2c,
241 294
 			break;
242 295
 
243 296
 		/* Select offset */
244
-		if ( ( rc = i2c_send_byte ( basher, offset++ ) ) != 0 )
297
+		if ( ( rc = i2c_send_byte ( basher, offset ) ) != 0 )
245 298
 			break;
246 299
 		
247 300
 		/* Select device for reading */
248
-		if ( ( rc = i2c_select ( basher, i2cdev, I2C_READ ) ) != 0 )
301
+		if ( ( rc = i2c_select ( basher, i2cdev, offset,
302
+					 I2C_READ ) ) != 0 )
249 303
 			break;
250 304
 
251 305
 		/* Read byte */
252
-		*data++ = i2c_recv_byte ( basher );
253
-		DBG ( "%02x ", *(data - 1) );
306
+		*data = i2c_recv_byte ( basher );
307
+		DBGC ( basher, "%02x ", *data );
254 308
 	}
255 309
 	
256
-	DBG ( "%s\n", ( rc ? "failed" : "" ) );
310
+	DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) );
257 311
 	i2c_stop ( basher );
258 312
 	return rc;
259 313
 }
@@ -279,12 +333,14 @@ static int i2c_bit_write ( struct i2c_interface *i2c,
279 333
 	struct bit_basher *basher = &i2cbit->basher;
280 334
 	int rc = 0;
281 335
 
282
-	DBG ( "Writing to I2C device %x: ", i2cdev->address );
336
+	DBGC ( basher, "I2CBIT %p writing to device %x: ",
337
+	       basher, i2cdev->dev_addr );
283 338
 
284
-	while ( 1 ) {
339
+	for ( ; ; data++, offset++ ) {
285 340
 
286 341
 		/* Select device for writing */
287
-		if ( ( rc = i2c_select ( basher, i2cdev, I2C_WRITE ) ) != 0 )
342
+		if ( ( rc = i2c_select ( basher, i2cdev, offset,
343
+					 I2C_WRITE ) ) != 0 )
288 344
 			break;
289 345
 		
290 346
 		/* Abort at end of data */
@@ -292,16 +348,16 @@ static int i2c_bit_write ( struct i2c_interface *i2c,
292 348
 			break;
293 349
 
294 350
 		/* Select offset */
295
-		if ( ( rc = i2c_send_byte ( basher, offset++ ) ) != 0 )
351
+		if ( ( rc = i2c_send_byte ( basher, offset ) ) != 0 )
296 352
 			break;
297 353
 		
298 354
 		/* Write data to device */
299
-		DBG ( "%02x ", *data );
300
-		if ( ( rc = i2c_send_byte ( basher, *data++ ) ) != 0 )
355
+		DBGC ( basher, "%02x ", *data );
356
+		if ( ( rc = i2c_send_byte ( basher, *data ) ) != 0 )
301 357
 			break;
302 358
 	}
303 359
 	
304
-	DBG ( "%s\n", ( rc ? "failed" : "" ) );
360
+	DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) );
305 361
 	i2c_stop ( basher );
306 362
 	return rc;
307 363
 }
@@ -310,13 +366,26 @@ static int i2c_bit_write ( struct i2c_interface *i2c,
310 366
  * Initialise I2C bit-bashing interface
311 367
  *
312 368
  * @v i2cbit		I2C bit-bashing interface
369
+ * @v bash_op		Bit-basher operations
313 370
  */
314
-void init_i2c_bit_basher ( struct i2c_bit_basher *i2cbit ) {
371
+int init_i2c_bit_basher ( struct i2c_bit_basher *i2cbit,
372
+			  struct bit_basher_operations *bash_op ) {
315 373
 	struct bit_basher *basher = &i2cbit->basher;
316
-	
374
+	int rc;
375
+
376
+	/* Initialise data structures */
377
+	basher->op = bash_op;
317 378
 	assert ( basher->op->read != NULL );
318 379
 	assert ( basher->op->write != NULL );
319 380
 	i2cbit->i2c.read = i2c_bit_read;
320 381
 	i2cbit->i2c.write = i2c_bit_write;
321
-	i2c_stop ( basher );
382
+
383
+	/* Reset I2C bus */
384
+	if ( ( rc = i2c_reset ( basher ) ) != 0 ) {
385
+		DBGC ( basher, "I2CBIT %p could not reset I2C bus: %s\n",
386
+		       basher, strerror ( rc ) );
387
+		return rc;
388
+	}
389
+
390
+	return 0;
322 391
 }

+ 3
- 3
src/drivers/net/etherfabric.c View File

@@ -1069,9 +1069,9 @@ static struct bit_basher_operations ef1002_basher_ops = {
1069 1069
 };
1070 1070
 
1071 1071
 static void ef1002_init_eeprom ( struct efab_nic *efab ) {
1072
-	efab->ef1002_i2c.basher.op = &ef1002_basher_ops;
1073
-	init_i2c_bit_basher ( &efab->ef1002_i2c );
1074
-	efab->ef1002_eeprom.address = EF1_EEPROM_I2C_ID;
1072
+	init_i2c_bit_basher ( &efab->ef1002_i2c,
1073
+			      &ef1002_basher_ops );
1074
+	init_i2c_eeprom ( &efab->ef1002_eeprom, EF1_EEPROM_I2C_ID );
1075 1075
 }
1076 1076
 
1077 1077
 /**

+ 63
- 5
src/include/gpxe/i2c.h View File

@@ -8,6 +8,7 @@
8 8
  */
9 9
 
10 10
 #include <stdint.h>
11
+#include <gpxe/bitbash.h>
11 12
 
12 13
 /** An I2C device
13 14
  *
@@ -15,10 +16,35 @@
15 16
  * is accessed via an I2C interface.
16 17
  */
17 18
 struct i2c_device {
18
-	/** Address of this device */
19
-	unsigned int address;
20
-	/** Flag indicating a ten-bit address format */
21
-	int tenbit;
19
+	/** Address of this device
20
+	 *
21
+	 * The actual address sent on the bus will look like
22
+	 *
23
+	 *    <start> <device address> <word address overflow> <r/w>
24
+	 *
25
+	 * The "word address overflow" is any excess bits from the
26
+	 * word address, i.e. any portion that does not fit within the
27
+	 * defined word address length.
28
+	 */
29
+	unsigned int dev_addr;
30
+	/** Device address length, in bytes
31
+	 *
32
+	 * This is the number of bytes that comprise the device
33
+	 * address, defined to be the portion that terminates with the
34
+	 * read/write bit.
35
+	 */
36
+	unsigned int dev_addr_len;
37
+	/** Word adddress length, in bytes
38
+	 *
39
+	 * This is the number of bytes that comprise the word address,
40
+	 * defined to be the portion that starts after the read/write
41
+	 * bit and ends before the first data byte.
42
+	 *
43
+	 * For some devices, this length will be zero (i.e. the word
44
+	 * address is contained entirely within the "word address
45
+	 * overflow").
46
+	 */
47
+	unsigned int word_addr_len;
22 48
 };
23 49
 
24 50
 /** An I2C interface
@@ -91,6 +117,9 @@ enum {
91 117
 /** Delay required for bit-bashing operation */
92 118
 #define I2C_UDELAY 5
93 119
 
120
+/** Maximum number of cycles to use when attempting a bus reset */
121
+#define I2C_RESET_MAX_CYCLES 32
122
+
94 123
 /**
95 124
  * Check presence of I2C device
96 125
  *
@@ -106,6 +135,35 @@ static inline int i2c_check_presence ( struct i2c_interface *i2c,
106 135
 	return i2c->write ( i2c, i2cdev, 0, NULL, 0 );
107 136
 }
108 137
 
109
-extern void init_i2c_bit_basher ( struct i2c_bit_basher *i2cbit );
138
+extern int init_i2c_bit_basher ( struct i2c_bit_basher *i2cbit,
139
+				 struct bit_basher_operations *bash_op );
140
+
141
+/**
142
+ * Initialise generic I2C EEPROM device
143
+ *
144
+ * @v i2cdev		I2C device
145
+ */
146
+static inline __always_inline void
147
+init_i2c_eeprom ( struct i2c_device *i2cdev, unsigned int dev_addr ) {
148
+	i2cdev->dev_addr = dev_addr;
149
+	i2cdev->dev_addr_len = 1;
150
+	i2cdev->word_addr_len = 1;
151
+}
152
+
153
+/**
154
+ * Initialise Atmel AT24C11
155
+ *
156
+ * @v i2cdev		I2C device
157
+ */
158
+static inline __always_inline void
159
+init_at24c11 ( struct i2c_device *i2cdev ) {
160
+	/* This chip has no device address; it must be the only chip
161
+	 * on the bus.  The word address is contained entirely within
162
+	 * the device address field.
163
+	 */
164
+	i2cdev->dev_addr = 0;
165
+	i2cdev->dev_addr_len = 1;
166
+	i2cdev->word_addr_len = 0;
167
+}
110 168
 
111 169
 #endif /* _GPXE_I2C_H */

Loading…
Cancel
Save