Преглед изворни кода

Migrated etherfabric driver to using generic SPI layer.

tags/v0.9.3
Michael Brown пре 18 година
родитељ
комит
d62c83a350
2 измењених фајлова са 101 додато и 127 уклоњено
  1. 58
    127
      src/drivers/net/etherfabric.c
  2. 43
    0
      src/include/gpxe/spi.h

+ 58
- 127
src/drivers/net/etherfabric.c Прегледај датотеку

@@ -22,7 +22,7 @@
22 22
 #include <gpxe/pci.h>
23 23
 #include <gpxe/bitbash.h>
24 24
 #include <gpxe/i2c.h>
25
-#include <gpxe/nvs.h>
25
+#include <gpxe/spi.h>
26 26
 #include "timer.h"
27 27
 #define dma_addr_t unsigned long
28 28
 #include "etherfabric.h"
@@ -208,13 +208,15 @@ struct efab_nic {
208 208
 	/** INT_REG_KER for Falcon */
209 209
 	efab_oword_t int_ker __attribute__ (( aligned ( 16 ) ));
210 210
 
211
-	/** EEPROM access */
211
+	/** I2C access */
212 212
 	struct i2c_bit_basher ef1002_i2c;
213 213
 	unsigned long ef1002_i2c_outputs;
214 214
 	struct i2c_device ef1002_eeprom;
215 215
 
216
-	/** NVS access */
217
-	struct nvs_device nvs;
216
+	/** SPI access */
217
+	struct spi_bus spi;
218
+	struct spi_device falcon_flash;
219
+	struct spi_device falcon_eeprom;
218 220
 };
219 221
 
220 222
 /**************************************************************************
@@ -2209,19 +2211,6 @@ static int falcon_reset ( struct efab_nic *efab ) {
2209 2211
 	return 1;
2210 2212
 }
2211 2213
 
2212
-/** SPI device */
2213
-struct efab_spi_device {
2214
-	/** Device ID */
2215
-	unsigned int device_id;
2216
-	/** Address length (in bytes) */
2217
-	unsigned int addr_len;
2218
-	/** Device size */
2219
-	unsigned int len;
2220
-};
2221
-
2222
-#define SPI_WRITE_CMD 0x02
2223
-#define SPI_READ_CMD 0x03
2224
-
2225 2214
 /**
2226 2215
  * Wait for SPI command completion
2227 2216
  *
@@ -2242,97 +2231,76 @@ static int falcon_spi_wait ( struct efab_nic *efab ) {
2242 2231
 }
2243 2232
 
2244 2233
 /**
2245
- * Perform SPI read
2234
+ * Perform SPI read/write
2246 2235
  *
2247 2236
  */
2248
-static int falcon_spi_read ( struct efab_nic *efab,
2249
-			     struct efab_spi_device *spi, int address,
2250
-			     void *data, unsigned int len ) {
2237
+static int falcon_spi_rw ( struct spi_bus *bus, struct spi_device *device,
2238
+			   unsigned int command, int address,
2239
+			   const void *data_out, void *data_in, size_t len ) {
2240
+	struct efab_nic *efab = container_of ( bus, struct efab_nic, spi );
2251 2241
 	efab_oword_t reg;
2252 2242
 
2253 2243
 	/* Program address register */
2254 2244
 	EFAB_POPULATE_OWORD_1 ( reg, FCN_EE_SPI_HADR_ADR, address );
2255 2245
 	falcon_write ( efab, &reg, FCN_EE_SPI_HADR_REG_KER );
2256 2246
 	
2257
-	/* Issue read command */
2247
+	/* Program data register, if applicable */
2248
+	if ( data_out ) {
2249
+		memcpy ( &reg, data_out, len );
2250
+		falcon_write ( efab, &reg, FCN_EE_SPI_HDATA_REG_KER );
2251
+	}
2252
+
2253
+	/* Issue command */
2258 2254
 	EFAB_POPULATE_OWORD_7 ( reg,
2259 2255
 				FCN_EE_SPI_HCMD_CMD_EN, 1, 
2260
-				FCN_EE_SPI_HCMD_SF_SEL, spi->device_id,
2256
+				FCN_EE_SPI_HCMD_SF_SEL, device->slave,
2261 2257
 				FCN_EE_SPI_HCMD_DABCNT, len,
2262
-				FCN_EE_SPI_HCMD_READ, FCN_EE_SPI_READ,
2258
+				FCN_EE_SPI_HCMD_READ, ( data_out ?
2259
+					  FCN_EE_SPI_WRITE : FCN_EE_SPI_READ ),
2263 2260
 				FCN_EE_SPI_HCMD_DUBCNT, 0,
2264
-				FCN_EE_SPI_HCMD_ADBCNT, spi->addr_len,
2265
-				FCN_EE_SPI_HCMD_ENC, SPI_READ_CMD );
2261
+				FCN_EE_SPI_HCMD_ADBCNT,
2262
+				( device->address_len / 8 ),
2263
+				FCN_EE_SPI_HCMD_ENC, command );
2266 2264
 	falcon_write ( efab, &reg, FCN_EE_SPI_HCMD_REG_KER );
2267 2265
 	
2268
-	/* Wait for read to complete */
2266
+	/* Wait for operation to complete */
2269 2267
 	if ( ! falcon_spi_wait ( efab ) )
2270 2268
 		return 0;
2271
-	
2272
-	/* Read data */
2273
-	falcon_read ( efab, &reg, FCN_EE_SPI_HDATA_REG_KER );
2274
-	memcpy ( data, &reg, len );
2275 2269
 
2270
+	/* Read data, if applicable */
2271
+	if ( data_in ) {
2272
+		falcon_read ( efab, &reg, FCN_EE_SPI_HDATA_REG_KER );
2273
+		memcpy ( data_in, &reg, len );
2274
+	}
2275
+	
2276 2276
 	return 1;
2277 2277
 }
2278 2278
 
2279 2279
 /**
2280
- * Perform SPI write
2280
+ * Initialise SPI bus and devices
2281 2281
  *
2282 2282
  */
2283
-static int falcon_spi_write ( struct efab_nic *efab,
2284
-			      struct efab_spi_device *spi, int address,
2285
-			      const void *data, unsigned int len ) {
2286
-	efab_oword_t reg;
2287
-
2288
-	/* Program address register */
2289
-	EFAB_POPULATE_OWORD_1 ( reg, FCN_EE_SPI_HADR_ADR, address );
2290
-	falcon_write ( efab, &reg, FCN_EE_SPI_HADR_REG_KER );
2291
-	
2292
-	/* Program data register */
2293
-	memcpy ( &reg, data, len );
2294
-	falcon_write ( efab, &reg, FCN_EE_SPI_HDATA_REG_KER );
2283
+static void falcon_init_spi ( struct efab_nic *efab ) {
2284
+	/* Initialise SPI bus */
2285
+	efab->spi.rw = falcon_spi_rw;
2286
+	efab->falcon_eeprom.bus = &efab->spi;
2287
+	efab->falcon_eeprom.slave = FCN_EE_SPI_EEPROM;
2288
+	efab->falcon_flash.bus = &efab->spi;
2289
+	efab->falcon_flash.slave = FCN_EE_SPI_FLASH;
2295 2290
 
2296
-	/* Issue write command */
2297
-	EFAB_POPULATE_OWORD_7 ( reg,
2298
-				FCN_EE_SPI_HCMD_CMD_EN, 1, 
2299
-				FCN_EE_SPI_HCMD_SF_SEL, spi->device_id,
2300
-				FCN_EE_SPI_HCMD_DABCNT, len,
2301
-				FCN_EE_SPI_HCMD_READ, FCN_EE_SPI_WRITE,
2302
-				FCN_EE_SPI_HCMD_DUBCNT, 0,
2303
-				FCN_EE_SPI_HCMD_ADBCNT, spi->addr_len,
2304
-				FCN_EE_SPI_HCMD_ENC, SPI_WRITE_CMD );
2305
-	falcon_write ( efab, &reg, FCN_EE_SPI_HCMD_REG_KER );
2306
-	
2307
-	/* Wait for read to complete */
2308
-	if ( ! falcon_spi_wait ( efab ) )
2309
-		return 0;
2310
-	
2311
-	return 1;
2291
+	/* Initialise EEPROM, if present */
2292
+	if ( efab->has_flash ) {
2293
+		init_at25f1024 ( &efab->falcon_flash );
2294
+		init_at25040 ( &efab->falcon_eeprom );
2295
+	} else {
2296
+		init_mc25xx640 ( &efab->falcon_eeprom );
2297
+		/* Falcon's SPI interface cannot support a block size
2298
+		 * larger than 16, so forcibly reduce it
2299
+		 */
2300
+		efab->falcon_eeprom.nvs.block_size = 16;
2301
+	}
2312 2302
 }
2313 2303
 
2314
-#define AT25F1024_ADDR_LEN 3
2315
-#define AT25040_ADDR_LEN 1
2316
-#define MC25XX640_ADDR_LEN 2
2317
-
2318
-/** Falcon Flash SPI device */
2319
-static struct efab_spi_device falcon_spi_flash = {
2320
-	.device_id	= FCN_EE_SPI_FLASH,
2321
-	.addr_len	= AT25F1024_ADDR_LEN,
2322
-};
2323
-
2324
-/** Falcon EEPROM SPI device */
2325
-static struct efab_spi_device falcon_spi_large_eeprom = {
2326
-	.device_id	= FCN_EE_SPI_EEPROM,
2327
-	.addr_len	= MC25XX640_ADDR_LEN,
2328
-};
2329
-
2330
-/** Falcon EEPROM SPI device */
2331
-static struct efab_spi_device falcon_spi_small_eeprom = {
2332
-	.device_id	= FCN_EE_SPI_EEPROM,
2333
-	.addr_len	= AT25040_ADDR_LEN,
2334
-};
2335
-
2336 2304
 /** Offset of MAC address within EEPROM or Flash */
2337 2305
 #define FALCON_MAC_ADDRESS_OFFSET(port) ( 0x310 + 0x08 * (port) )
2338 2306
 
@@ -2341,51 +2309,14 @@ static struct efab_spi_device falcon_spi_small_eeprom = {
2341 2309
  *
2342 2310
  */
2343 2311
 static int falcon_read_eeprom ( struct efab_nic *efab ) {
2344
-	struct efab_spi_device *spi;
2345
-
2346
-	/* Determine the SPI device containing the MAC address */
2347
-	spi = efab->has_flash ? &falcon_spi_flash : &falcon_spi_large_eeprom;
2348
-	return falcon_spi_read ( efab, spi,
2349
-				 FALCON_MAC_ADDRESS_OFFSET ( efab->port ),
2350
-				 efab->mac_addr, sizeof ( efab->mac_addr ) );
2351
-}
2352
-
2353
-#define FALCON_NVS_OFFSET 0x000
2354
-
2355
-static int falcon_read_nvs ( struct nvs_device *nvs, unsigned int offset,
2356
-			     void *data, size_t len ) {
2357
-	struct efab_nic *efab = container_of ( nvs, struct efab_nic, nvs );
2358
-	struct efab_spi_device *spi = &falcon_spi_small_eeprom;
2359
-
2360
-	while ( len ) {
2361
-		if ( ! falcon_spi_read ( efab, spi,
2362
-					 ( offset + FALCON_NVS_OFFSET ),
2363
-					 data, 16 ) ) {
2364
-			return -EIO;
2365
-		}
2366
-		data += 16;
2367
-		offset += 16;
2368
-		len -=16;
2369
-	}
2370
-	return 0;
2371
-}
2312
+	struct nvs_device *nvs;
2372 2313
 
2373
-static int falcon_write_nvs ( struct nvs_device *nvs, unsigned int offset,
2374
-			      const void *data, size_t len ) {
2375
-	struct efab_nic *efab = container_of ( nvs, struct efab_nic, nvs );
2376
-	struct efab_spi_device *spi = &falcon_spi_large_eeprom;
2314
+	/* Determine the NVS device containing the MAC address */
2315
+	nvs = ( efab->has_flash ?
2316
+		&efab->falcon_flash.nvs : &efab->falcon_eeprom.nvs );
2377 2317
 
2378
-	while ( len ) {
2379
-		if ( ! falcon_spi_write ( efab, spi,
2380
-					 ( offset + FALCON_NVS_OFFSET ),
2381
-					 data, 16 ) ) {
2382
-			return -EIO;
2383
-		}
2384
-		data += 16;
2385
-		offset += 16;
2386
-		len -=16;
2387
-	}
2388
-	return 0;
2318
+	return nvs_read ( nvs, FALCON_MAC_ADDRESS_OFFSET ( efab->port ),
2319
+			  efab->mac_addr, sizeof ( efab->mac_addr ) );
2389 2320
 }
2390 2321
 
2391 2322
 /** RX descriptor */
@@ -2962,12 +2893,12 @@ static int falcon_init_nic ( struct efab_nic *efab ) {
2962 2893
 	} else {
2963 2894
 		falcon_read ( efab, &reg, FCN_GPIO_CTL_REG_KER );
2964 2895
 		efab->has_flash = EFAB_OWORD_FIELD ( reg, FCN_FLASH_PRESENT );
2965
-		efab->has_eeprom = EFAB_OWORD_FIELD ( reg, FCN_EEPROM_PRESENT );
2896
+		efab->has_eeprom = EFAB_OWORD_FIELD ( reg, FCN_EEPROM_PRESENT);
2966 2897
 	}
2967
-
2968 2898
 	EFAB_LOG ( "flash is %s, EEPROM is %s\n",
2969 2899
 		   ( efab->has_flash ? "present" : "absent" ),
2970 2900
 		   ( efab->has_eeprom ? "present" : "absent" ) );
2901
+	falcon_init_spi ( efab );
2971 2902
 
2972 2903
 	/* Set up TX and RX descriptor caches in SRAM */
2973 2904
 	EFAB_POPULATE_OWORD_1 ( reg, FCN_SRM_TX_DC_BASE_ADR,

+ 43
- 0
src/include/gpxe/spi.h Прегледај датотеку

@@ -193,4 +193,47 @@ extern int spi_read ( struct nvs_device *nvs, unsigned int address,
193 193
 extern int spi_write ( struct nvs_device *nvs, unsigned int address,
194 194
 		       const void *data, size_t len );
195 195
 
196
+/**
197
+ * @defgroup spidevs SPI device types
198
+ * @{
199
+ */
200
+
201
+static inline __attribute__ (( always_inline )) void
202
+init_spi ( struct spi_device *device ) {
203
+	device->nvs.word_len_log2 = 0;
204
+	device->command_len = 8,
205
+	device->nvs.read = spi_read;
206
+	device->nvs.write = spi_write;	
207
+}
208
+
209
+/** Atmel AT25F1024 serial flash */
210
+static inline __attribute__ (( always_inline )) void
211
+init_at25f1024 ( struct spi_device *device ) {
212
+	device->address_len = 24;
213
+	device->nvs.size = ( 128 * 1024 );
214
+	device->nvs.block_size = 256;
215
+	init_spi ( device );
216
+}
217
+
218
+/** Atmel 25040 serial EEPROM */
219
+static inline __attribute__ (( always_inline )) void
220
+init_at25040 ( struct spi_device *device ) {
221
+	device->address_len = 8;
222
+	device->munge_address = 1;
223
+	device->nvs.size = 512;
224
+	device->nvs.block_size = 8;
225
+	init_spi ( device );
226
+}
227
+
228
+/** Microchip 25XX640 serial EEPROM */
229
+static inline __attribute__ (( always_inline )) void
230
+init_mc25xx640 ( struct spi_device *device ) {
231
+	device->address_len = 16;
232
+	device->nvs.size = ( 8 * 1024 );
233
+	device->nvs.block_size = 32;
234
+	init_spi ( device );
235
+}
236
+
237
+/** @} */
238
+
196 239
 #endif /* _GPXE_SPI_H */

Loading…
Откажи
Сачувај