eepromread: support for reading from /dev/eeprom

eepromread could only read EEPROMs through the /dev/i2c interface.
Once the cat24c256 driver is started and claims/reserves the
device, it can no longer be read through the /dev/i2c interface.

This patch adds support for reading from EEPROMs through the
/dev/eeprom interface. For example, to read the on-board eeprom
on the BBB, one would do `eepromread -f /dev/eepromb1s50 -i`.

Change-Id: If08ce37231e593982eeb109bdd6d5458ad271108
This commit is contained in:
Thomas Cort 2013-11-10 12:06:27 -05:00
parent 9a00643262
commit 13054fd168
4 changed files with 67 additions and 35 deletions

View File

@ -16,9 +16,12 @@
* Attempt to read the board info from an eeprom on this board. * Attempt to read the board info from an eeprom on this board.
*/ */
static int board_info_beaglebone(int fd, i2c_addr_t address, int flags); static int board_info_beaglebone(int fd, i2c_addr_t address, int flags,
static int board_info_cape_a0(int fd, i2c_addr_t address, int flags); enum device_types device_type);
static int board_info_cape_a1(int fd, i2c_addr_t address, int flags); static int board_info_cape_a0(int fd, i2c_addr_t address, int flags,
enum device_types device_type);
static int board_info_cape_a1(int fd, i2c_addr_t address, int flags,
enum device_types device_type);
/* Memory Layout of the BeagleBone and BeagleBone Black EEPROM */ /* Memory Layout of the BeagleBone and BeagleBone Black EEPROM */
typedef struct beaglebone_info typedef struct beaglebone_info
@ -68,7 +71,8 @@ typedef struct cape_info_a1
} cape_info_a1_t; } cape_info_a1_t;
static int static int
board_info_beaglebone(int fd, i2c_addr_t address, int flags) board_info_beaglebone(int fd, i2c_addr_t address, int flags,
enum device_types device_type)
{ {
int r; int r;
int i, j; int i, j;
@ -76,7 +80,7 @@ board_info_beaglebone(int fd, i2c_addr_t address, int flags)
beaglebone_info_t boneinfo; beaglebone_info_t boneinfo;
r = eeprom_read(fd, address, 0x0000, &boneinfo, r = eeprom_read(fd, address, 0x0000, &boneinfo,
sizeof(beaglebone_info_t), flags); sizeof(beaglebone_info_t), flags, device_type);
if (r == -1) { if (r == -1) {
fprintf(stderr, "Failed to read BeagleBone info r=%d\n", r); fprintf(stderr, "Failed to read BeagleBone info r=%d\n", r);
return -1; return -1;
@ -102,7 +106,8 @@ board_info_beaglebone(int fd, i2c_addr_t address, int flags)
} }
static int static int
board_info_cape_a0(int fd, i2c_addr_t address, int flags) board_info_cape_a0(int fd, i2c_addr_t address, int flags,
enum device_types device_type)
{ {
int r; int r;
int i, j; int i, j;
@ -110,7 +115,7 @@ board_info_cape_a0(int fd, i2c_addr_t address, int flags)
cape_info_a0_t capeinfo; cape_info_a0_t capeinfo;
r = eeprom_read(fd, address, 0x0000, &capeinfo, r = eeprom_read(fd, address, 0x0000, &capeinfo,
sizeof(cape_info_a0_t), flags); sizeof(cape_info_a0_t), flags, device_type);
if (r == -1) { if (r == -1) {
fprintf(stderr, "failed to read cape A0 info r=%d\n", r); fprintf(stderr, "failed to read cape A0 info r=%d\n", r);
return -1; return -1;
@ -148,7 +153,8 @@ board_info_cape_a0(int fd, i2c_addr_t address, int flags)
} }
static int static int
board_info_cape_a1(int fd, i2c_addr_t address, int flags) board_info_cape_a1(int fd, i2c_addr_t address, int flags,
enum device_types device_type)
{ {
int r; int r;
int i, j; int i, j;
@ -156,7 +162,7 @@ board_info_cape_a1(int fd, i2c_addr_t address, int flags)
cape_info_a1_t capeinfo; cape_info_a1_t capeinfo;
r = eeprom_read(fd, address, 0x0000, &capeinfo, r = eeprom_read(fd, address, 0x0000, &capeinfo,
sizeof(cape_info_a1_t), flags); sizeof(cape_info_a1_t), flags, device_type);
if (r == -1) { if (r == -1) {
fprintf(stderr, "failed to read cape A0 info r=%d\n", r); fprintf(stderr, "failed to read cape A0 info r=%d\n", r);
return -1; return -1;
@ -194,12 +200,14 @@ board_info_cape_a1(int fd, i2c_addr_t address, int flags)
} }
int int
board_info(int fd, i2c_addr_t address, int flags) board_info(int fd, i2c_addr_t address, int flags,
enum device_types device_type)
{ {
int r; int r;
uint8_t magic_number[6]; uint8_t magic_number[6];
r = eeprom_read(fd, address, 0x0000, &magic_number, 6, flags); r = eeprom_read(fd, address, 0x0000, &magic_number, 6, flags,
device_type);
if (r == -1) { if (r == -1) {
printf("%-16s: %s\n", "BOARD_NAME", "UNKNOWN"); printf("%-16s: %s\n", "BOARD_NAME", "UNKNOWN");
return 0; return 0;
@ -211,11 +219,11 @@ board_info(int fd, i2c_addr_t address, int flags)
/* Check if Cape Rev A0, Cape Rev A1, or on-board EEPROM */ /* Check if Cape Rev A0, Cape Rev A1, or on-board EEPROM */
if (magic_number[4] == 'A' && magic_number[5] == '0') { if (magic_number[4] == 'A' && magic_number[5] == '0') {
board_info_cape_a0(fd, address, flags); board_info_cape_a0(fd, address, flags, device_type);
} else if (magic_number[4] == 'A' && magic_number[5] == '1') { } else if (magic_number[4] == 'A' && magic_number[5] == '1') {
board_info_cape_a1(fd, address, flags); board_info_cape_a1(fd, address, flags, device_type);
} else { } else {
board_info_beaglebone(fd, address, flags); board_info_beaglebone(fd, address, flags, device_type);
} }
} else { } else {
printf("%-16s: %s\n", "BOARD_NAME", "UNKNOWN"); printf("%-16s: %s\n", "BOARD_NAME", "UNKNOWN");

View File

@ -43,6 +43,10 @@ number is sent with the memory address. Use this when reading EDID.
.TP 20 .TP 20
.B eepromread -f /dev/i2c-3 -n .B eepromread -f /dev/i2c-3 -n
# read the EDID info from the display on I2C bus 3 on the BeagleBoard-xM. # read the EDID info from the display on I2C bus 3 on the BeagleBoard-xM.
.TP 20
.B eepromread -f /dev/eepromb1s50 -i
# access the EEPROM through the /dev/eeprom interface once the
cat24c256 driver has been started.
.SH DESCRIPTION .SH DESCRIPTION
.PP .PP
\fIeepromread\fR is a simple tool for viewing the contents of an EEPROM. \fIeepromread\fR is a simple tool for viewing the contents of an EEPROM.
@ -51,5 +55,5 @@ detect, \fIeepromread\fR can properly format each of the fields and display
the information via the \fI-i\fR command line option. the information via the \fI-i\fR command line option.
.SH NOTES .SH NOTES
If the \fIcat24c256\fR driver has claimed the EEPROM device that this If the \fIcat24c256\fR driver has claimed the EEPROM device that this
program is attempting to read from, then this program will fail. Once program is attempting to read from, then you must access it through
a driver claims an I2C device, the driver has exclusive access. the /dev/eeprom interface rather than the /dev/i2c interface.

View File

@ -15,8 +15,9 @@
#include "eepromread.h" #include "eepromread.h"
static int __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, static int __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr,
void *buf, size_t buflen, int flags); void *buf, size_t buflen, int flags, enum device_types device_type);
static int eeprom_dump(int fd, i2c_addr_t addr, int flags); static int eeprom_dump(int fd, i2c_addr_t addr, int flags,
enum device_types device_type);
#define DEFAULT_I2C_DEVICE "/dev/i2c-1" #define DEFAULT_I2C_DEVICE "/dev/i2c-1"
#define DEFAULT_I2C_ADDRESS 0x50 #define DEFAULT_I2C_ADDRESS 0x50
@ -26,16 +27,11 @@ static int eeprom_dump(int fd, i2c_addr_t addr, int flags);
* larger, so to read the whole EEPROM, the task is broken down into 128 byte * larger, so to read the whole EEPROM, the task is broken down into 128 byte
* chunks in eeprom_read(). __eeprom_read128() does the actual ioctl() to do * chunks in eeprom_read(). __eeprom_read128() does the actual ioctl() to do
* the read. * the read.
*
* A future enhancement might be to add support for the /dev/eeprom interface
* and if one way fails, fall back to the other. /dev/eeprom can fail if the
* eeprom driver isn't running and /dev/i2c can fail if the eeprom driver
* claimed the eeprom device.
*/ */
static int static int
__eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf, __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
size_t buflen, int flags) size_t buflen, int flags, enum device_types device_type)
{ {
int r; int r;
minix_i2c_ioctl_exec_t ioctl_exec; minix_i2c_ioctl_exec_t ioctl_exec;
@ -46,6 +42,20 @@ __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
return -1; return -1;
} }
/* if /dev/eeprom, then use read() */
if (device_type == EEPROM_DEVICE) {
off_t offset;
offset = lseek(fd, memaddr, SEEK_SET);
if (offset != memaddr) {
return -1;
}
return read(fd, buf, buflen);
}
/* else /dev/i2c, use i2c_ioctl_exec_t interface */
memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t)); memset(&ioctl_exec, '\0', sizeof(minix_i2c_ioctl_exec_t));
ioctl_exec.iie_op = I2C_OP_READ_WITH_STOP; ioctl_exec.iie_op = I2C_OP_READ_WITH_STOP;
@ -77,7 +87,7 @@ __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
int int
eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf, eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
size_t buflen, int flags) size_t buflen, int flags, enum device_types device_type)
{ {
int r; int r;
uint16_t i; uint16_t i;
@ -87,11 +97,11 @@ eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
return -1; return -1;
} }
for (i = 0; i < buflen; i += 128) { for (i = 0; i < buflen; i += 128) {
r = __eeprom_read128(fd, addr, memaddr + i, buf + i, r = __eeprom_read128(fd, addr, memaddr + i, buf + i,
((buflen - i) < 128) ? (buflen - i) : 128, flags); ((buflen - i) < 128) ? (buflen - i) : 128, flags,
device_type);
if (r == -1) { if (r == -1) {
return -1; return -1;
} }
@ -104,14 +114,14 @@ eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
* Read 256 bytes and print it to the screen in HEX and ASCII. * Read 256 bytes and print it to the screen in HEX and ASCII.
*/ */
static int static int
eeprom_dump(int fd, i2c_addr_t addr, int flags) eeprom_dump(int fd, i2c_addr_t addr, int flags, enum device_types device_type)
{ {
int i, j, r; int i, j, r;
uint8_t buf[256]; uint8_t buf[256];
memset(buf, '\0', 256); memset(buf, '\0', 256);
r = eeprom_read(fd, addr, 0x0000, buf, 256, flags); r = eeprom_read(fd, addr, 0x0000, buf, 256, flags, device_type);
if (r == -1) { if (r == -1) {
return r; return r;
} }
@ -163,6 +173,7 @@ main(int argc, char *argv[])
int ch, iflag = 0, read_flags = 0; int ch, iflag = 0, read_flags = 0;
char *device = DEFAULT_I2C_DEVICE; char *device = DEFAULT_I2C_DEVICE;
i2c_addr_t address = DEFAULT_I2C_ADDRESS; i2c_addr_t address = DEFAULT_I2C_ADDRESS;
enum device_types device_type = DEFAULT_DEVICE;
setprogname(*argv); setprogname(*argv);
@ -185,6 +196,10 @@ main(int argc, char *argv[])
} }
} }
/* determine whether to use /dev/i2c or /dev/eeprom interface */
device_type =
strstr(device, "i2c") == NULL ? EEPROM_DEVICE : I2C_DEVICE;
fd = open(device, O_RDWR); fd = open(device, O_RDWR);
if (fd == -1) { if (fd == -1) {
fprintf(stderr, "open(): %s\n", strerror(errno)); fprintf(stderr, "open(): %s\n", strerror(errno));
@ -192,15 +207,16 @@ main(int argc, char *argv[])
} }
if (iflag == 1) { if (iflag == 1) {
r = board_info(fd, address, read_flags); r = board_info(fd, address, read_flags, device_type);
if (r == -1) { if (r == -1) {
fprintf(stderr, "board_info(): %s\n", strerror(errno)); fprintf(stderr, "board_info(): %s\n", strerror(errno));
return 1; return 1;
} }
} else { } else {
r = eeprom_dump(fd, address, read_flags); r = eeprom_dump(fd, address, read_flags, device_type);
if (r == -1) { if (r == -1) {
fprintf(stderr, "eeprom_dump(): %s\n", strerror(errno)); fprintf(stderr, "eeprom_dump(): %s\n",
strerror(errno));
return 1; return 1;
} }
} }
@ -213,4 +229,3 @@ main(int argc, char *argv[])
return 0; return 0;
} }

View File

@ -1,8 +1,13 @@
#ifndef __EEPROMREAD_H #ifndef __EEPROMREAD_H
#define __EEPROMREAD_H #define __EEPROMREAD_H
enum device_types { I2C_DEVICE, EEPROM_DEVICE };
#define DEFAULT_DEVICE I2C_DEVICE
int eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf, int eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
size_t buflen, int flags); size_t buflen, int flags, enum device_types device_type);
int board_info(int fd, i2c_addr_t address, int flags);
int board_info(int fd, i2c_addr_t address, int flags,
enum device_types device_type);
#endif /* __EEPROMREAD_H */ #endif /* __EEPROMREAD_H */