mirror of
https://github.com/ipxe/ipxe
synced 2025-12-22 21:11:03 +03:00
Abstracted out part of the concept of an SPI device to a generalised NVS
device. Separated the mechanisms of non-volatile storage access and non-volatile stored options.
This commit is contained in:
21
src/include/gpxe/nvo.h
Normal file
21
src/include/gpxe/nvo.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef _GPXE_NVO_H
|
||||
#define _GPXE_NVO_H
|
||||
|
||||
/** @file
|
||||
*
|
||||
* Non-volatile stored options
|
||||
*
|
||||
*/
|
||||
|
||||
struct nvs_device;
|
||||
struct dhcp_option_block;
|
||||
|
||||
struct nvs_options {
|
||||
struct nvs_device *nvs;
|
||||
struct dhcp_option_block *options;
|
||||
};
|
||||
|
||||
extern int nvo_register ( struct nvs_options *nvo );
|
||||
extern void nvo_unregister ( struct nvs_options *nvo );
|
||||
|
||||
#endif /* _GPXE_NVO_H */
|
||||
@@ -9,22 +9,53 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct nvs_operations;
|
||||
|
||||
/** A non-volatile storage device */
|
||||
struct nvs_device {
|
||||
struct dhcp_option_block *options;
|
||||
size_t len;
|
||||
struct nvs_operations *op;
|
||||
};
|
||||
|
||||
struct nvs_operations {
|
||||
int ( * read ) ( struct nvs_device *nvs, unsigned int offset,
|
||||
/** Word length, in bits */
|
||||
unsigned int word_len;
|
||||
/** Device size (in words) */
|
||||
unsigned int size;
|
||||
/** Data block size (in words)
|
||||
*
|
||||
* This is the block size used by the device. It must be a
|
||||
* power of two. Data reads and writes must not cross a block
|
||||
* boundary.
|
||||
*
|
||||
* Many devices allow reads to cross a block boundary, and
|
||||
* restrict only writes. For the sake of simplicity, we
|
||||
* assume that the same restriction applies to both reads and
|
||||
* writes.
|
||||
*/
|
||||
unsigned int block_size;
|
||||
/** Read data from 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
|
||||
*
|
||||
* Reads may not cross a block boundary.
|
||||
*/
|
||||
int ( * read ) ( struct nvs_device *nvs, unsigned int address,
|
||||
void *data, size_t len );
|
||||
int ( * write ) ( struct nvs_device *nvs, unsigned int offset,
|
||||
/** Write data to device
|
||||
*
|
||||
* @v nvs NVS device
|
||||
* @v address Address to which to write
|
||||
* @v data Data buffer
|
||||
* @v len Length of data buffer
|
||||
* @ret rc Return status code
|
||||
*
|
||||
* Writes may not cross a block boundary.
|
||||
*/
|
||||
int ( * write ) ( struct nvs_device *nvs, unsigned int address,
|
||||
const void *data, size_t len );
|
||||
};
|
||||
|
||||
extern int nvs_register ( struct nvs_device *nvs );
|
||||
extern void nvs_unregister ( struct nvs_device *nvs );
|
||||
extern int nvs_read ( struct nvs_device *nvs, unsigned int address,
|
||||
void *data, size_t len );
|
||||
extern int nvs_write ( struct nvs_device *nvs, unsigned int address,
|
||||
const void *data, size_t len );
|
||||
|
||||
#endif /* _GPXE_NVS_H */
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <gpxe/bitbash.h>
|
||||
#include <gpxe/nvs.h>
|
||||
|
||||
/**
|
||||
* @defgroup spicmds SPI commands
|
||||
@@ -75,32 +75,19 @@
|
||||
|
||||
/** @} */
|
||||
|
||||
struct spi_device;
|
||||
|
||||
/**
|
||||
* An SPI device type
|
||||
* An SPI device
|
||||
*
|
||||
* This data structure represents all the characteristics belonging to
|
||||
* a particular type of SPI device, e.g. "an Atmel 251024 serial flash",
|
||||
* or "a Microchip 25040 serial EEPROM".
|
||||
* This data structure represents a physical SPI device attached to an
|
||||
* SPI bus.
|
||||
*/
|
||||
struct spi_device_type {
|
||||
/** Word length, in bits */
|
||||
unsigned int word_len;
|
||||
/** Device size (in words) */
|
||||
unsigned int size;
|
||||
/** Data block size (in words)
|
||||
*
|
||||
* This is the block size used by the device. It must be a
|
||||
* power of two. Data reads and writes must not cross a block
|
||||
* boundary.
|
||||
*
|
||||
* Many devices allow reads to cross a block boundary, and
|
||||
* restrict only writes. For the sake of simplicity, we
|
||||
* assume that the same restriction applies to both reads and
|
||||
* writes.
|
||||
*/
|
||||
unsigned int block_size;
|
||||
struct spi_device {
|
||||
/** NVS device */
|
||||
struct nvs_device nvs;
|
||||
/** SPI bus to which device is attached */
|
||||
struct spi_bus *bus;
|
||||
/** Slave number */
|
||||
unsigned int slave;
|
||||
/** Command length, in bits */
|
||||
unsigned int command_len;
|
||||
/** Address length, in bits */
|
||||
@@ -113,64 +100,18 @@ struct spi_device_type {
|
||||
* commands should be munged in this way.
|
||||
*/
|
||||
unsigned int munge_address : 1;
|
||||
/** Read data from device
|
||||
*
|
||||
* @v device SPI device
|
||||
* @v address Address from which to read
|
||||
* @v data Data buffer
|
||||
* @v len Length of data buffer
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int ( * read ) ( struct spi_device *device, unsigned int address,
|
||||
void *data, size_t len );
|
||||
/** Write data to device
|
||||
*
|
||||
* @v device SPI device
|
||||
* @v address Address to which to write
|
||||
* @v data Data buffer
|
||||
* @v len Length of data buffer
|
||||
* @ret rc Return status code
|
||||
*/
|
||||
int ( * write ) ( struct spi_device *device, unsigned int address,
|
||||
const void *data, size_t len );
|
||||
};
|
||||
|
||||
/**
|
||||
* @defgroup spidevs SPI device types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Atmel AT25010 serial EEPROM */
|
||||
#define AT25010 { \
|
||||
.word_len = 8, \
|
||||
.size = 128, \
|
||||
.block_size = 8, \
|
||||
.command_len = 8, \
|
||||
.address_len = 8, \
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* An SPI device
|
||||
*
|
||||
* This data structure represents a real, physical SPI device attached
|
||||
* to an SPI controller. It comprises the device type plus
|
||||
* instantiation-specific information such as the slave number.
|
||||
*/
|
||||
struct spi_device {
|
||||
/** SPI device type */
|
||||
struct spi_device_type *type;
|
||||
/** SPI bus to which device is attached */
|
||||
struct spi_bus *bus;
|
||||
/** Slave number */
|
||||
unsigned int slave;
|
||||
};
|
||||
static inline __attribute__ (( always_inline )) struct spi_device *
|
||||
nvs_to_spi ( struct nvs_device *nvs ) {
|
||||
return container_of ( nvs, struct spi_device, nvs );
|
||||
}
|
||||
|
||||
/**
|
||||
* An SPI bus
|
||||
*
|
||||
*
|
||||
* This data structure represents an SPI bus controller capable of
|
||||
* issuing commands to attached SPI devices.
|
||||
*/
|
||||
struct spi_bus {
|
||||
/** SPI interface mode
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <gpxe/spi.h>
|
||||
#include <gpxe/bitbash.h>
|
||||
|
||||
/** A bit-bashing SPI bus */
|
||||
struct spi_bit_basher {
|
||||
|
||||
@@ -22,40 +22,48 @@
|
||||
|
||||
/** @} */
|
||||
|
||||
extern int threewire_read ( struct nvs_device *nvs, unsigned int address,
|
||||
void *data, size_t len );
|
||||
|
||||
/**
|
||||
* @defgroup spidevs SPI device types
|
||||
* @defgroup tdevs Three-wire device types
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Atmel AT93C46 serial EEPROM
|
||||
*
|
||||
* @v org Word size (8 or 16)
|
||||
*/
|
||||
#define AT93C46( org ) { \
|
||||
.word_len = (org), \
|
||||
.size = ( 1024 / (org) ), \
|
||||
.block_size = 1, \
|
||||
.command_len = 3, \
|
||||
.address_len = ( ( (org) == 8 ) ? 7 : 6 ), \
|
||||
.read = threewire_read, \
|
||||
}
|
||||
static inline __attribute__ (( always_inline )) void
|
||||
init_at93cx6 ( struct spi_device *device, unsigned int organisation ) {
|
||||
device->nvs.word_len = organisation;
|
||||
device->nvs.block_size = 1;
|
||||
device->command_len = 3,
|
||||
device->nvs.read = threewire_read;
|
||||
}
|
||||
|
||||
/** Atmel AT93C56 serial EEPROM
|
||||
/**
|
||||
* Initialise Atmel AT93C46 serial EEPROM
|
||||
*
|
||||
* @v org Word size (8 or 16)
|
||||
* @v device SPI device
|
||||
* @v organisation Word organisation (8 or 16)
|
||||
*/
|
||||
#define AT93C56( org ) { \
|
||||
.word_len = (org), \
|
||||
.size = ( 2048 / (org) ), \
|
||||
.block_size = 1, \
|
||||
.command_len = 3, \
|
||||
.address_len = ( ( (org) == 8 ) ? 9 : 8 ), \
|
||||
.read = threewire_read, \
|
||||
}
|
||||
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 );
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
extern int threewire_read ( struct spi_device *device, unsigned int address,
|
||||
void *data, size_t len );
|
||||
|
||||
#endif /* _GPXE_THREEWIRE_H */
|
||||
|
||||
Reference in New Issue
Block a user