diff options
author | Michael Brown | 2006-05-26 17:39:24 +0200 |
---|---|---|
committer | Michael Brown | 2006-05-26 17:39:24 +0200 |
commit | aa2468babe4c5c052f41790cefb344c27f77852f (patch) | |
tree | 1d6b3b1e5c7666f479f678c6c5bcb3be3ab78ead /src | |
parent | Need write permission to /dev/net/tun, not just read. (diff) | |
download | ipxe-aa2468babe4c5c052f41790cefb344c27f77852f.tar.gz ipxe-aa2468babe4c5c052f41790cefb344c27f77852f.tar.xz ipxe-aa2468babe4c5c052f41790cefb344c27f77852f.zip |
Added abstraction layer for a three-wire serial device (e.g. the EEPROM
used on RTL8139 cards).
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 1 | ||||
-rw-r--r-- | src/drivers/nvs/threewire.c | 68 | ||||
-rw-r--r-- | src/include/gpxe/nvs/threewire.h | 102 |
3 files changed, 171 insertions, 0 deletions
diff --git a/src/Makefile b/src/Makefile index 77d2fc93..4f44c14a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -138,6 +138,7 @@ SRCDIRS += drivers/bus SRCDIRS += drivers/net SRCDIRS += drivers/block SRCDIRS += drivers/scsi +SRCDIRS += drivers/nvs SRCDIRS += interface/pxe # NON_AUTO_SRCS lists files that are excluded from the normal diff --git a/src/drivers/nvs/threewire.c b/src/drivers/nvs/threewire.c new file mode 100644 index 00000000..4673606d --- /dev/null +++ b/src/drivers/nvs/threewire.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <timer.h> +#include <gpxe/nvs/threewire.h> + +/** @file + * + * Three-wire serial interface + * + */ + +/** + * Read from a three-wire device + * + * @v three Three-wire interface + * @v address Address + * @ret data Data + */ +unsigned long threewire_read ( struct threewire *three, + unsigned long address ) { + struct threewire_operations *ops = three->ops; + unsigned long command; + unsigned long data; + int i; + + ops->setcs ( three, 1 ); + + /* Send command and address */ + command = threewire_cmd_read ( three, address ); + for ( i = ( threewire_cmd_len ( three ) - 1 ) ; i >= 0 ; i-- ) { + ops->setdi ( three, ( command >> i ) & 0x1 ); + udelay ( three->udelay ); + ops->setsk ( three, 1 ); + udelay ( three->udelay ); + ops->setsk ( three, 0 ); + } + + /* Read back data */ + data = 0; + for ( i = three->datasize ; i ; i-- ) { + udelay ( three->udelay ); + ops->setsk ( three, 1 ); + udelay ( three->udelay ); + data <<= 1; + data |= ops->getdo ( three ); + ops->setsk ( three, 0 ); + } + + ops->setcs ( three, 0 ); + + return data; +} diff --git a/src/include/gpxe/nvs/threewire.h b/src/include/gpxe/nvs/threewire.h new file mode 100644 index 00000000..a0bb2fd3 --- /dev/null +++ b/src/include/gpxe/nvs/threewire.h @@ -0,0 +1,102 @@ +#ifndef _GPXE_NVS_THREEWIRE_H +#define _GPXE_NVS_THREEWIRE_H + +/** @file + * + * Three-wire serial interface + * + */ + +struct threewire; + +/** Three-wire interface methods */ +struct threewire_operations { + /** + * Set status of Chip Select line + * + * @v three Three-wire interface + * @v cs New status for chip select line + */ + void ( * setcs ) ( struct threewire *three, int cs ); + /** + * Set status of Serial Clock line + * + * @v three Three-wire interface + * @v sk New status for serial clock line + */ + void ( * setsk ) ( struct threewire *three, int sk ); + /** + * Set status of Data Input line + * + * @v three Three-wire interface + * @v di New status for data input line + */ + void ( * setdi ) ( struct threewire *three, int di ); + /** + * Get status of Data Output line + * + * @v three Three-wire interface + * @ret do Status of data output line + */ + int ( * getdo ) ( struct threewire *three ); +}; + +/** + * A three-wire serial interface + * + * This interface consists of a clock line (SK), data input (DI) and + * data output (DO). There is also a chip select line (CS) which is + * integral to the operation of the device, but Atmel still calls it a + * three-wire interface. + * + */ +struct threewire { + /** Interface methods */ + struct threewire_operations *ops; + /** Address size (in bits) */ + unsigned int adrsize; + /** Data size (in bits) */ + unsigned int datasize; + /** Delay between SK transitions (in us) */ + unsigned int udelay; +}; + +/** + * Calculate read command for a specified address + * + * @v three Three-wire interface + * @v address Address + * @ret cmd Command + */ +static inline __attribute__ (( always_inline )) unsigned long +threewire_cmd_read ( struct threewire *three, unsigned long address ) { + return ( ( 0x6 << three->adrsize ) | address ); +} + +/** + * Calculate command length + * + * @v three Three-wire interface + * @ret len Command length, in bits + */ +static inline __attribute__ (( always_inline )) int +threewire_cmd_len ( struct threewire *three ) { + return ( three->adrsize + 3 ); +} + +/* Constants for some standard parts */ +#define AT93C46_ORG8_ADRSIZE 7 +#define AT93C46_ORG8_DATASIZE 8 +#define AT93C46_ORG16_ADRSIZE 6 +#define AT93C46_ORG16_DATASIZE 16 +#define AT93C46_UDELAY 1 +#define AT93C56_ORG8_ADRSIZE 9 +#define AT93C56_ORG8_DATASIZE 8 +#define AT93C56_ORG16_ADRSIZE 8 +#define AT93C56_ORG16_DATASIZE 16 +#define AT93C56_UDELAY 1 + +extern unsigned long threewire_read ( struct threewire *three, + unsigned long address ); + +#endif /* _GPXE_NVS_THREEWIRE_H */ |