diff options
Diffstat (limited to 'src/drivers')
| -rw-r--r-- | src/drivers/bitbash/bitbash.c | 4 | ||||
| -rw-r--r-- | src/drivers/bitbash/i2c_bit.c | 4 | ||||
| -rw-r--r-- | src/drivers/bitbash/spi_bit.c | 125 | ||||
| -rw-r--r-- | src/drivers/net/etherfabric.c | 8 | ||||
| -rw-r--r-- | src/drivers/net/rtl8139.c | 50 | ||||
| -rw-r--r-- | src/drivers/nvs/threewire.c | 39 |
6 files changed, 123 insertions, 107 deletions
diff --git a/src/drivers/bitbash/bitbash.c b/src/drivers/bitbash/bitbash.c index 19add4ce0..ec94feeea 100644 --- a/src/drivers/bitbash/bitbash.c +++ b/src/drivers/bitbash/bitbash.c @@ -37,7 +37,7 @@ */ void write_bit ( struct bit_basher *basher, unsigned int bit_id, unsigned long data ) { - basher->write ( basher, bit_id, ( data ? -1UL : 0 ) ); + basher->op->write ( basher, bit_id, ( data ? -1UL : 0 ) ); } /** @@ -52,5 +52,5 @@ void write_bit ( struct bit_basher *basher, unsigned int bit_id, * it needs to apply. */ int read_bit ( struct bit_basher *basher, unsigned int bit_id ) { - return ( basher->read ( basher, bit_id ) ? -1UL : 0 ); + return ( basher->op->read ( basher, bit_id ) ? -1UL : 0 ); } diff --git a/src/drivers/bitbash/i2c_bit.c b/src/drivers/bitbash/i2c_bit.c index f0a9b936f..d8fbacc0e 100644 --- a/src/drivers/bitbash/i2c_bit.c +++ b/src/drivers/bitbash/i2c_bit.c @@ -314,8 +314,8 @@ static int i2c_bit_write ( struct i2c_interface *i2c, void init_i2c_bit_basher ( struct i2c_bit_basher *i2cbit ) { struct bit_basher *basher = &i2cbit->basher; - assert ( basher->read != NULL ); - assert ( basher->write != NULL ); + assert ( basher->op->read != NULL ); + assert ( basher->op->write != NULL ); i2cbit->i2c.read = i2c_bit_read; i2cbit->i2c.write = i2c_bit_write; i2c_stop ( basher ); diff --git a/src/drivers/bitbash/spi_bit.c b/src/drivers/bitbash/spi_bit.c index 20ad412cc..462fd72e8 100644 --- a/src/drivers/bitbash/spi_bit.c +++ b/src/drivers/bitbash/spi_bit.c @@ -19,11 +19,12 @@ #include <stddef.h> #include <stdint.h> #include <string.h> +#include <byteswap.h> #include <errno.h> #include <assert.h> #include <timer.h> #include <gpxe/bitbash.h> -#include <gpxe/spi.h> +#include <gpxe/spi_bit.h> /** @file * @@ -32,65 +33,43 @@ */ /** Delay between SCLK changes and around SS changes */ -static void spi_delay ( void ) { - udelay ( SPI_UDELAY ); +static void spi_bit_delay ( void ) { + udelay ( SPI_BIT_UDELAY ); } +/** Chip select line will be asserted */ +#define SELECT_SLAVE 0 + +/** Chip select line will be deasserted */ +#define DESELECT_SLAVE SPI_MODE_SSPOL + /** * Select/deselect slave * - * @v spi SPI bit-bashing interface + * @v spibit SPI bit-bashing interface * @v slave Slave number * @v state Slave select state * - * @c state must be set to zero to select the specified slave, or to - * @c SPI_MODE_SSPOL to deselect the slave. + * @c state must be @c SELECT_SLAVE or @c DESELECT_SLAVE. */ static void spi_bit_set_slave_select ( struct spi_bit_basher *spibit, unsigned int slave, unsigned int state ) { struct bit_basher *basher = &spibit->basher; - state ^= ( spibit->spi.mode & SPI_MODE_SSPOL ); + state ^= ( spibit->bus.mode & SPI_MODE_SSPOL ); DBG ( "Setting slave %d select %s\n", slave, ( state ? "high" : "low" ) ); - spi_delay(); + spi_bit_delay(); write_bit ( basher, SPI_BIT_SS ( slave ), state ); - spi_delay(); -} - -/** - * Select slave - * - * @v spi SPI interface - * @v slave Slave number - */ -static void spi_bit_select_slave ( struct spi_interface *spi, - unsigned int slave ) { - struct spi_bit_basher *spibit - = container_of ( spi, struct spi_bit_basher, spi ); - - spibit->slave = slave; - spi_bit_set_slave_select ( spibit, slave, 0 ); + spi_bit_delay(); } /** - * Deselect slave + * Transfer bits over SPI bit-bashing bus * - * @v spi SPI interface - */ -static void spi_bit_deselect_slave ( struct spi_interface *spi ) { - struct spi_bit_basher *spibit - = container_of ( spi, struct spi_bit_basher, spi ); - - spi_bit_set_slave_select ( spibit, spibit->slave, SPI_MODE_SSPOL ); -} - -/** - * Transfer bits over SPI bit-bashing interface - * - * @v spi SPI interface + * @v bus SPI bus * @v data_out TX data buffer (or NULL) * @v data_in RX data buffer (or NULL) * @v len Length of transfer (in @b bits) @@ -101,19 +80,19 @@ static void spi_bit_deselect_slave ( struct spi_interface *spi ) { * NULL, then the data sent will be all zeroes. If @c data_in is * NULL, then the incoming data will be discarded. */ -static void spi_bit_transfer ( struct spi_interface *spi, const void *data_out, - void *data_in, unsigned int len ) { - struct spi_bit_basher *spibit - = container_of ( spi, struct spi_bit_basher, spi ); +static void spi_bit_transfer ( struct spi_bit_basher *spibit, + const void *data_out, void *data_in, + unsigned int len ) { + struct spi_bus *bus = &spibit->bus; struct bit_basher *basher = &spibit->basher; - unsigned int sclk = ( ( spi->mode & SPI_MODE_CPOL ) ? 1 : 0 ); - unsigned int cpha = ( ( spi->mode & SPI_MODE_CPHA ) ? 1 : 0 ); + unsigned int sclk = ( ( bus->mode & SPI_MODE_CPOL ) ? 1 : 0 ); + unsigned int cpha = ( ( bus->mode & SPI_MODE_CPHA ) ? 1 : 0 ); unsigned int offset; unsigned int mask; unsigned int bit; int step; - DBG ( "Transferring %d bits in mode %x\n", len, spi->mode ); + DBG ( "Transferring %d bits in mode %x\n", len, bus->mode ); for ( step = ( ( len * 2 ) - 1 ) ; step >= 0 ; step-- ) { /* Calculate byte offset within data and bit mask */ @@ -145,21 +124,65 @@ static void spi_bit_transfer ( struct spi_interface *spi, const void *data_out, } /* Toggle clock line */ - spi_delay(); + spi_bit_delay(); sclk = ~sclk; write_bit ( basher, SPI_BIT_SCLK, sclk ); } } /** + * Read/write data via SPI bit-bashing bus + * + * @v bus SPI bus + * @v device SPI device + * @v command Command + * @v address Address to read/write (<0 for no address) + * @v data_out TX data buffer (or NULL) + * @v data_in RX data buffer (or NULL) + * @v len Length of transfer (in @b words) + * @ret rc Return status code + */ +static int spi_bit_rw ( struct spi_bus *bus, struct spi_device *device, + unsigned int command, int address, + const void *data_out, void *data_in, + unsigned int len ) { + struct spi_bit_basher *spibit + = container_of ( bus, struct spi_bit_basher, bus ); + struct spi_device_type *devtype = device->type; + uint32_t tmp; + + /* Assert chip select on specified slave */ + spi_bit_set_slave_select ( spibit, device->slave, SELECT_SLAVE ); + + /* Transmit command */ + assert ( devtype->command_len <= ( 8 * sizeof ( tmp ) ) ); + tmp = cpu_to_le32 ( command ); + spi_bit_transfer ( spibit, &tmp, NULL, devtype->command_len ); + + /* Transmit address, if present */ + if ( address >= 0 ) { + assert ( devtype->address_len <= ( 8 * sizeof ( tmp ) ) ); + tmp = cpu_to_le32 ( address ); + spi_bit_transfer ( spibit, &tmp, NULL, devtype->address_len ); + } + + /* Transmit/receive data */ + spi_bit_transfer ( spibit, data_out, data_in, + ( len * devtype->word_len ) ); + + /* Deassert chip select on specified slave */ + spi_bit_set_slave_select ( spibit, device->slave, DESELECT_SLAVE ); + + return 0; +} + +/** * Initialise SPI bit-bashing interface * * @v spibit SPI bit-bashing interface */ void init_spi_bit_basher ( struct spi_bit_basher *spibit ) { - assert ( &spibit->basher.read != NULL ); - assert ( &spibit->basher.write != NULL ); - spibit->spi.select_slave = spi_bit_select_slave; - spibit->spi.deselect_slave = spi_bit_deselect_slave; - spibit->spi.transfer = spi_bit_transfer; + assert ( &spibit->basher.op->read != NULL ); + assert ( &spibit->basher.op->write != NULL ); + spibit->bus.rw = spi_bit_rw; } diff --git a/src/drivers/net/etherfabric.c b/src/drivers/net/etherfabric.c index 1b5f29a7b..9afe65df1 100644 --- a/src/drivers/net/etherfabric.c +++ b/src/drivers/net/etherfabric.c @@ -1058,9 +1058,13 @@ static int ef1002_i2c_read_bit ( struct bit_basher *basher, return ( EFAB_DWORD_FIELD ( reg, EF1_EEPROM ) & mask ); } +static struct bit_basher_operations ef1002_basher_ops = { + .read = ef1002_i2c_read_bit, + .write = ef1002_i2c_write_bit, +}; + static void ef1002_init_eeprom ( struct efab_nic *efab ) { - efab->ef1002_i2c.basher.write = ef1002_i2c_write_bit; - efab->ef1002_i2c.basher.read = ef1002_i2c_read_bit; + efab->ef1002_i2c.basher.op = &ef1002_basher_ops; init_i2c_bit_basher ( &efab->ef1002_i2c ); efab->ef1002_eeprom.address = EF1_EEPROM_I2C_ID; } diff --git a/src/drivers/net/rtl8139.c b/src/drivers/net/rtl8139.c index d42d3c2d2..c1a29e4f2 100644 --- a/src/drivers/net/rtl8139.c +++ b/src/drivers/net/rtl8139.c @@ -77,7 +77,7 @@ #include <gpxe/ethernet.h> #include <gpxe/pkbuff.h> #include <gpxe/netdevice.h> -#include <gpxe/spi.h> +#include <gpxe/spi_bit.h> #include <gpxe/threewire.h> #define TX_RING_SIZE 4 @@ -97,7 +97,7 @@ struct rtl8139_nic { struct rtl8139_tx tx; struct rtl8139_rx rx; struct spi_bit_basher spibit; - struct threewire_device eeprom; + struct spi_device eeprom; }; /* Tuning Parameters */ @@ -204,11 +204,6 @@ enum RxConfigBits { /* Offsets within EEPROM (these are word offsets) */ #define EE_MAC 7 -static inline struct rtl8139_nic * -basher_to_rtl ( struct bit_basher *basher ) { - return container_of ( basher, struct rtl8139_nic, spibit.basher ); -} - static const uint8_t rtl_ee_bits[] = { [SPI_BIT_SCLK] = EE_SK, [SPI_BIT_MOSI] = EE_DI, @@ -218,7 +213,8 @@ static const uint8_t rtl_ee_bits[] = { static int rtl_spi_read_bit ( struct bit_basher *basher, unsigned int bit_id ) { - struct rtl8139_nic *rtl = basher_to_rtl ( basher ); + struct rtl8139_nic *rtl = container_of ( basher, struct rtl8139_nic, + spibit.basher ); uint8_t mask = rtl_ee_bits[bit_id]; uint8_t eereg; @@ -228,7 +224,8 @@ static int rtl_spi_read_bit ( struct bit_basher *basher, static void rtl_spi_write_bit ( struct bit_basher *basher, unsigned int bit_id, unsigned long data ) { - struct rtl8139_nic *rtl = basher_to_rtl ( basher ); + struct rtl8139_nic *rtl = container_of ( basher, struct rtl8139_nic, + spibit.basher ); uint8_t mask = rtl_ee_bits[bit_id]; uint8_t eereg; @@ -238,6 +235,14 @@ static void rtl_spi_write_bit ( struct bit_basher *basher, outb ( eereg, rtl->ioaddr + Cfg9346 ); } +static struct bit_basher_operations rtl_basher_ops = { + .read = rtl_spi_read_bit, + .write = rtl_spi_write_bit, +}; + +static struct spi_device_type rtl_ee9346 = AT93C46 ( 16 ); +static struct spi_device_type rtl_ee9356 = AT93C56 ( 16 ); + /** * Set up for EEPROM access * @@ -247,19 +252,15 @@ static void rtl_init_eeprom ( struct rtl8139_nic *rtl ) { int ee9356; /* Initialise three-wire bus */ - rtl->spibit.basher.read = rtl_spi_read_bit; - rtl->spibit.basher.write = rtl_spi_write_bit; - rtl->spibit.spi.mode = SPI_MODE_THREEWIRE; + rtl->spibit.basher.op = &rtl_basher_ops; + rtl->spibit.bus.mode = SPI_MODE_THREEWIRE; init_spi_bit_basher ( &rtl->spibit ); /* Detect EEPROM type and initialise three-wire device */ ee9356 = ( inw ( rtl->ioaddr + RxConfig ) & Eeprom9356 ); - DBG ( "EEPROM is an %s\n", ee9356 ? "AT93C56" : "AT93C46" ); - rtl->eeprom.adrsize = - ( ee9356 ? AT93C56_ORG16_ADRSIZE : AT93C46_ORG16_ADRSIZE ); - rtl->eeprom.datasize = - ( ee9356 ? AT93C56_ORG16_DATASIZE : AT93C46_ORG16_DATASIZE ); - rtl->eeprom.spi = &rtl->spibit.spi; + DBG ( "EEPROM is an %s\n", ( ee9356 ? "AT93C56" : "AT93C46" ) ); + rtl->eeprom.type = ( ee9356 ? &rtl_ee9356 : &rtl_ee9346 ); + rtl->eeprom.bus = &rtl->spibit.bus; } /** @@ -269,18 +270,15 @@ static void rtl_init_eeprom ( struct rtl8139_nic *rtl ) { * @v mac_addr Buffer to contain MAC address (ETH_ALEN bytes) */ static void rtl_read_mac ( struct rtl8139_nic *rtl, uint8_t *mac_addr ) { - union { - uint16_t word; - uint8_t bytes[2]; - } u; + + struct spi_device *device = &rtl->eeprom; int i; DBG ( "MAC address is " ); for ( i = EE_MAC ; i < ( EE_MAC + ( ETH_ALEN / 2 ) ) ; i++ ) { - u.word = cpu_to_le16 ( threewire_read ( &rtl->eeprom, i ) ); - *mac_addr++ = u.bytes[0]; - *mac_addr++ = u.bytes[1]; - DBG ( "%02x%02x", u.bytes[0], u.bytes[1] ); + device->type->read ( device, i, mac_addr, 1 ); + DBG ( "%02x%02x", mac_addr[0], mac_addr[1] ); + mac_addr += 2; } DBG ( "\n" ); } diff --git a/src/drivers/nvs/threewire.c b/src/drivers/nvs/threewire.c index 92f9a24b7..fd360037a 100644 --- a/src/drivers/nvs/threewire.c +++ b/src/drivers/nvs/threewire.c @@ -17,8 +17,7 @@ */ #include <stddef.h> -#include <byteswap.h> -#include <gpxe/spi.h> +#include <assert.h> #include <gpxe/threewire.h> /** @file @@ -27,31 +26,23 @@ * */ -/** - * Read from a three-wire device +/** Read data from three-wire device * - * @v three Three-wire device - * @v address Address - * @ret data Data + * @v device SPI device + * @v address Address from which to read + * @v data Data buffer + * @v len Length of data to read, in @b words + * @ret rc Return status code */ -unsigned long threewire_read ( struct threewire_device *three, - unsigned long address ) { - struct spi_interface *spi = three->spi; - uint32_t data; +int threewire_read ( struct spi_device *device, unsigned int address, + void *data, unsigned int len ) { + struct spi_bus *bus = device->bus; - /* Activate chip select line */ - spi->select_slave ( spi, three->slave ); + assert ( bus->mode == SPI_MODE_THREEWIRE ); - /* Send command and address */ - data = cpu_to_le32 ( threewire_cmd_read ( three, address ) ); - spi->transfer ( spi, &data, NULL, threewire_cmd_len ( three ) ); - - /* Read back data */ - data = 0; - spi->transfer ( spi, NULL, &data, three->datasize ); + DBG ( "3wire %p reading words [%04x,%04x)\n", device, + address, ( address + len ) ); - /* Deactivate chip select line */ - spi->deselect_slave ( spi ); - - return le32_to_cpu ( data );; + return bus->rw ( bus, device, THREEWIRE_READ, address, + NULL, data, len ); } |
