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.
*/
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);
static int board_info_cape_a1(int fd, i2c_addr_t address, int flags);
static int board_info_beaglebone(int fd, i2c_addr_t address, int flags,
enum device_types device_type);
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 */
typedef struct beaglebone_info
@ -68,7 +71,8 @@ typedef struct cape_info_a1
} cape_info_a1_t;
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 i, j;
@ -76,7 +80,7 @@ board_info_beaglebone(int fd, i2c_addr_t address, int flags)
beaglebone_info_t boneinfo;
r = eeprom_read(fd, address, 0x0000, &boneinfo,
sizeof(beaglebone_info_t), flags);
sizeof(beaglebone_info_t), flags, device_type);
if (r == -1) {
fprintf(stderr, "Failed to read BeagleBone info r=%d\n", r);
return -1;
@ -102,7 +106,8 @@ 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)
board_info_cape_a0(int fd, i2c_addr_t address, int flags,
enum device_types device_type)
{
int r;
int i, j;
@ -110,7 +115,7 @@ board_info_cape_a0(int fd, i2c_addr_t address, int flags)
cape_info_a0_t 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) {
fprintf(stderr, "failed to read cape A0 info r=%d\n", r);
return -1;
@ -148,7 +153,8 @@ board_info_cape_a0(int fd, i2c_addr_t address, int flags)
}
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 i, j;
@ -156,7 +162,7 @@ board_info_cape_a1(int fd, i2c_addr_t address, int flags)
cape_info_a1_t 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) {
fprintf(stderr, "failed to read cape A0 info r=%d\n", r);
return -1;
@ -194,12 +200,14 @@ board_info_cape_a1(int fd, i2c_addr_t address, int flags)
}
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;
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) {
printf("%-16s: %s\n", "BOARD_NAME", "UNKNOWN");
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 */
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') {
board_info_cape_a1(fd, address, flags);
board_info_cape_a1(fd, address, flags, device_type);
} else {
board_info_beaglebone(fd, address, flags);
board_info_beaglebone(fd, address, flags, device_type);
}
} else {
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
.B eepromread -f /dev/i2c-3 -n
# 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
.PP
\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.
.SH NOTES
If the \fIcat24c256\fR driver has claimed the EEPROM device that this
program is attempting to read from, then this program will fail. Once
a driver claims an I2C device, the driver has exclusive access.
program is attempting to read from, then you must access it through
the /dev/eeprom interface rather than the /dev/i2c interface.

View file

@ -15,8 +15,9 @@
#include "eepromread.h"
static int __eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr,
void *buf, size_t buflen, int flags);
static int eeprom_dump(int fd, i2c_addr_t addr, 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,
enum device_types device_type);
#define DEFAULT_I2C_DEVICE "/dev/i2c-1"
#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
* chunks in eeprom_read(). __eeprom_read128() does the actual ioctl() to do
* 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
__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;
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;
}
/* 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));
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
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;
uint16_t i;
@ -87,11 +97,11 @@ eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
return -1;
}
for (i = 0; i < buflen; i += 128) {
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) {
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.
*/
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;
uint8_t buf[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) {
return r;
}
@ -163,6 +173,7 @@ main(int argc, char *argv[])
int ch, iflag = 0, read_flags = 0;
char *device = DEFAULT_I2C_DEVICE;
i2c_addr_t address = DEFAULT_I2C_ADDRESS;
enum device_types device_type = DEFAULT_DEVICE;
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);
if (fd == -1) {
fprintf(stderr, "open(): %s\n", strerror(errno));
@ -192,15 +207,16 @@ main(int argc, char *argv[])
}
if (iflag == 1) {
r = board_info(fd, address, read_flags);
r = board_info(fd, address, read_flags, device_type);
if (r == -1) {
fprintf(stderr, "board_info(): %s\n", strerror(errno));
return 1;
}
} else {
r = eeprom_dump(fd, address, read_flags);
r = eeprom_dump(fd, address, read_flags, device_type);
if (r == -1) {
fprintf(stderr, "eeprom_dump(): %s\n", strerror(errno));
fprintf(stderr, "eeprom_dump(): %s\n",
strerror(errno));
return 1;
}
}
@ -213,4 +229,3 @@ main(int argc, char *argv[])
return 0;
}

View file

@ -1,8 +1,13 @@
#ifndef __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,
size_t buflen, int flags);
int board_info(int fd, i2c_addr_t address, int flags);
size_t buflen, int flags, enum device_types device_type);
int board_info(int fd, i2c_addr_t address, int flags,
enum device_types device_type);
#endif /* __EEPROMREAD_H */