mirror of
https://github.com/ipxe/ipxe
synced 2025-12-25 00:17:57 +03:00
Several SPI chips will respond to an SPI read command with a dummy zero bit immediately prior to the first real data bit. This can be used to autodetect the address length, provided that the command length and data length are already known, and that the MISO data line is tied high. Tested-by: Thomas Miletich <thomas.miletich@gmail.com> Debugged-by: Thomas Miletich <thomas.miletich@gmail.com>
93 lines
2.3 KiB
C
93 lines
2.3 KiB
C
#ifndef _GPXE_THREEWIRE_H
|
|
#define _GPXE_THREEWIRE_H
|
|
|
|
/** @file
|
|
*
|
|
* Three-wire serial interface
|
|
*
|
|
* The Atmel three-wire interface is a subset of the (newer) SPI
|
|
* interface, and is implemented here as a layer on top of the SPI
|
|
* support.
|
|
*/
|
|
|
|
FILE_LICENCE ( GPL2_OR_LATER );
|
|
|
|
#include <gpxe/spi.h>
|
|
#include <limits.h>
|
|
|
|
/**
|
|
* @defgroup tcmds Three-wire commands
|
|
* @{
|
|
*/
|
|
|
|
/** 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 );
|
|
extern int threewire_detect_address_len ( struct spi_device *device );
|
|
|
|
/**
|
|
* @defgroup tdevs Three-wire device types
|
|
* @{
|
|
*/
|
|
|
|
static inline __attribute__ (( always_inline )) void
|
|
init_at93cx6 ( struct spi_device *device, unsigned int organisation ) {
|
|
device->nvs.word_len_log2 = ( ( organisation == 8 ) ? 0 : 1 );
|
|
device->nvs.block_size = 1;
|
|
device->command_len = 3,
|
|
device->nvs.read = threewire_read;
|
|
device->nvs.write = threewire_write;
|
|
}
|
|
|
|
/**
|
|
* Initialise Atmel AT93C46 serial EEPROM
|
|
*
|
|
* @v device SPI device
|
|
* @v organisation Word organisation (8 or 16)
|
|
*/
|
|
static inline __attribute__ (( always_inline )) void
|
|
init_at93c46 ( struct spi_device *device, unsigned int organisation ) {
|
|
device->nvs.size = ( 1024 / organisation );
|
|
device->address_len = ( ( organisation == 8 ) ? 7 : 6 );
|
|
init_at93cx6 ( device, organisation );
|
|
}
|
|
|
|
/**
|
|
* Initialise Atmel AT93C56 serial EEPROM
|
|
*
|
|
* @v device SPI device
|
|
* @v organisation Word organisation (8 or 16)
|
|
*/
|
|
static inline __attribute__ (( always_inline )) void
|
|
init_at93c56 ( struct spi_device *device, unsigned int organisation ) {
|
|
device->nvs.size = ( 2048 / organisation );
|
|
device->address_len = ( ( organisation == 8 ) ? 9 : 8 );
|
|
init_at93cx6 ( device, organisation );
|
|
}
|
|
|
|
/** @} */
|
|
|
|
#endif /* _GPXE_THREEWIRE_H */
|