From d2bf7abe754543f459da9ff2a0080715bf742b67 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Wed, 6 Dec 2006 19:51:58 +0000 Subject: [PATCH] Added write support for three-wire devices (e.g. the RTL8139 EEPROM) --- src/drivers/nvs/threewire.c | 42 +++++++++++++++++++++++++++++++++++- src/include/gpxe/threewire.h | 20 +++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/drivers/nvs/threewire.c b/src/drivers/nvs/threewire.c index 043cc8fc..3ce2a906 100644 --- a/src/drivers/nvs/threewire.c +++ b/src/drivers/nvs/threewire.c @@ -18,6 +18,7 @@ #include #include +#include #include /** @file @@ -26,7 +27,8 @@ * */ -/** Read data from three-wire device +/** + * Read data from three-wire device * * @v nvs NVS device * @v address Address from which to read @@ -46,3 +48,41 @@ int threewire_read ( struct nvs_device *nvs, unsigned int address, return bus->rw ( bus, device, THREEWIRE_READ, address, NULL, data, len ); } + +/** + * Write data to three-wire device + * + * @v nvs NVS device + * @v address Address from which to read + * @v data Data buffer + * @v len Length of data buffer + * @ret rc Return status code + */ +int threewire_write ( struct nvs_device *nvs, unsigned int address, + const void *data, size_t len ) { + struct spi_device *device = nvs_to_spi ( nvs ); + struct spi_bus *bus = device->bus; + int rc; + + assert ( bus->mode == SPI_MODE_THREEWIRE ); + + DBG ( "3wire %p writing %d bytes at %04x\n", device, len, address ); + + /* Enable device for writing */ + if ( ( rc = bus->rw ( bus, device, THREEWIRE_EWEN, + THREEWIRE_EWEN_ADDRESS, NULL, NULL, 0 ) ) != 0 ) + return rc; + + /* Write data */ + if ( ( rc = bus->rw ( bus, device, THREEWIRE_WRITE, address, + data, NULL, len ) ) != 0 ) + return rc; + + /* Our model of an SPI bus doesn't provide a mechanism for + * "assert CS, wait for MISO to become high, so just wait for + * long enough to ensure that the write has completed. + */ + mdelay ( THREEWIRE_WRITE_MDELAY ); + + return 0; +} diff --git a/src/include/gpxe/threewire.h b/src/include/gpxe/threewire.h index d60e1a71..865fc25d 100644 --- a/src/include/gpxe/threewire.h +++ b/src/include/gpxe/threewire.h @@ -11,6 +11,7 @@ */ #include +#include /** * @defgroup tcmds Three-wire commands @@ -20,10 +21,28 @@ /** Read data from memory array */ #define THREEWIRE_READ 0x6 +/** Write data to memory array */ +#define THREEWIRE_WRITE 0x5 + +/** Write enable */ +#define THREEWIRE_EWEN 0x4 + +/** Address to be used for write enable command */ +#define THREEWIRE_EWEN_ADDRESS INT_MAX + +/** Time to wait for write cycles to complete + * + * This is sufficient for AT93C46/AT93C56 devices, but may need to be + * increased in future when other devices are added. + */ +#define THREEWIRE_WRITE_MDELAY 10 + /** @} */ extern int threewire_read ( struct nvs_device *nvs, unsigned int address, void *data, size_t len ); +extern int threewire_write ( struct nvs_device *nvs, unsigned int address, + const void *data, size_t len ); /** * @defgroup tdevs Three-wire device types @@ -36,6 +55,7 @@ init_at93cx6 ( struct spi_device *device, unsigned int organisation ) { device->nvs.block_size = 1; device->command_len = 3, device->nvs.read = threewire_read; + device->nvs.write = threewire_write; } /**