]> Zhao Yanbai Git Server - minix.git/commitdiff
i2c: increase BUFLEN/CMDLEN to 128, add page flag. 88/688/2
authorThomas Cort <tcort@minix3.org>
Fri, 26 Jul 2013 23:44:52 +0000 (19:44 -0400)
committerThomas Cort <tcort@minix3.org>
Sat, 27 Jul 2013 12:21:37 +0000 (08:21 -0400)
128 byte reads are much more common than 32 byte reads. The message
passing + setup/teardown for a read is much more expensive, in terms
of time, than the reading itself. A slightly bigger struct is well
worth the time savings. This reduces read times for /dev/eeprom
from 57 seconds per 4KB to 14 seconds.

Additionally, make sending the page address in the eeprom driver
and utility optional. This can save a little time when reading
within the same page and allows support for smaller devices that
don't support pages (example: chips containing EDID).

Change-Id: Ie48087caee40c11fa241d1555fce9309ddd27b43

commands/eepromread/board_info.c
commands/eepromread/eepromread.1
commands/eepromread/eepromread.c
commands/eepromread/eepromread.h
drivers/cat24c256/cat24c256.c
include/minix/com.h
sys/dev/i2c/i2c_io.h

index 0000868370352641d939b44b29436151b7f14a2c..66d000baa13f6ee7989c48895704c924e7f59132 100644 (file)
@@ -18,7 +18,7 @@
  * In the future, this could be expanded to support cape EEPROMs.
  */
 
-static int board_info_beaglebone(int fd, i2c_addr_t address);
+static int board_info_beaglebone(int fd, i2c_addr_t address, int flags);
 
 /* Memory Layout of the BeagleBone and BeagleBone Black EEPROM */
 typedef struct beaglebone_info
@@ -32,7 +32,7 @@ typedef struct beaglebone_info
 } beaglebone_info_t;
 
 static int
-board_info_beaglebone(int fd, i2c_addr_t address)
+board_info_beaglebone(int fd, i2c_addr_t address, int flags)
 {
        int r;
        int i, j;
@@ -40,7 +40,7 @@ board_info_beaglebone(int fd, i2c_addr_t address)
        beaglebone_info_t boneinfo;
 
        r = eeprom_read(fd, address, 0x0000, &boneinfo,
-           sizeof(beaglebone_info_t));
+           sizeof(beaglebone_info_t), flags);
        if (r == -1) {
                fprintf(stderr, "Failed to read BeagleBone info r=%d\n", r);
                return -1;
@@ -65,12 +65,12 @@ board_info_beaglebone(int fd, i2c_addr_t address)
 }
 
 int
-board_info(int fd, i2c_addr_t address)
+board_info(int fd, i2c_addr_t address, int flags)
 {
        int r;
        uint8_t magic_number[4];
 
-       r = eeprom_read(fd, address, 0x0000, &magic_number, 4);
+       r = eeprom_read(fd, address, 0x0000, &magic_number, 4, flags);
        if (r == -1) {
                printf("%-16s: %s\n", "BOARD_NAME", "UNKNOWN");
                return 0;
@@ -78,7 +78,7 @@ board_info(int fd, i2c_addr_t address)
 
        if (magic_number[0] == 0xaa && magic_number[1] == 0x55 &&
            magic_number[2] == 0x33 && magic_number[3] == 0xee) {
-               board_info_beaglebone(fd, address);
+               board_info_beaglebone(fd, address, flags);
        } else {
                printf("%-16s: %s\n", "BOARD_NAME", "UNKNOWN");
        }
index a3bbfc91d2a8a16f42bcade79828a84917218cf5..53115ac999b666fee87732e7abd5a56599d9b80b 100644 (file)
@@ -3,6 +3,7 @@
 eepromread \- read data from an EEPROM
 .SH SYNOPSIS
 \fBeepromread\fR [\fB\-i\fR] [\fB\-f\fR \fIdev\fR] [\fB\-a\fR \fIslave_addr\fR]
+[\fB\-n\fR]
 .br
 .de FL
 .TP
@@ -24,6 +25,11 @@ eepromread \- read data from an EEPROM
 .TP 5
 .B \-a
 # Use \fIslave_address\fR instead of \fI0x50\fR.
+.TP 5
+.B \-n
+# Do not send the page number when addressing the memory on the EEPROM. Some
+smaller EEPROM chips aren't organized into pages and get confused if a page
+number is sent with the memory address. Use this when reading EDID.
 .SH EXAMPLES
 .TP 20
 .B eepromread -i
@@ -34,6 +40,9 @@ eepromread \- read data from an EEPROM
 .TP 20
 .B eepromread -f /dev/i2c-3 -a 0x54
 # display the first 256 bytes of the EEPROM on I2C bus 3, slave address 0x54.
+.TP 20
+.B eepromread -f /dev/i2c-3 -n
+# read the EDID info from the display on I2C bus 3 on the BeagleBoard-xM.
 .SH DESCRIPTION
 .PP
 \fIeepromread\fR is a simple tool for viewing the contents of an EEPROM.
index 1d9e84f586d577349ce4a4ac3f9c45347c36f281..4ecee6bdcb22a4d010fd53690a2e2d45308d2d4c 100644 (file)
@@ -1,4 +1,5 @@
 #include <minix/i2c.h>
+#include <minix/com.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
 
 #include "eepromread.h"
 
-static int __eeprom_read32(int fd, i2c_addr_t addr, uint16_t memaddr,
-    void *buf, size_t buflen);
-static int eeprom_dump(int fd, i2c_addr_t addr);
+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);
 
 #define DEFAULT_I2C_DEVICE "/dev/i2c-1"
 #define DEFAULT_I2C_ADDRESS 0x50
 
 /*
- * The /dev interface only supports 32 byte reads/writes and the EEPROM is
- * larger, so to read the whole EEPROM, the task is broken down into 32 byte
- * chunks in eeprom_read(). __eeprom_read32() does the actual ioctl() to do
+ * The /dev interface only supports 128 byte reads/writes and the EEPROM is
+ * 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
@@ -33,8 +34,8 @@ static int eeprom_dump(int fd, i2c_addr_t addr);
  */
 
 static int
-__eeprom_read32(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
-    size_t buflen)
+__eeprom_read128(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
+    size_t buflen, int flags)
 {
        int r;
        minix_i2c_ioctl_exec_t ioctl_exec;
@@ -51,10 +52,16 @@ __eeprom_read32(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
        ioctl_exec.iie_addr = addr;
 
        /* set the address to read from */
-       ioctl_exec.iie_cmd[0] = ((memaddr >> 8) & 0xff);
-       ioctl_exec.iie_cmd[1] = (memaddr & 0xff);
-       ioctl_exec.iie_cmdlen = 2;
-
+       if ((BDEV_NOPAGE & flags) == BDEV_NOPAGE) {
+               /* reading within the current page */
+               ioctl_exec.iie_cmd[0] = (memaddr & 0xff);
+               ioctl_exec.iie_cmdlen = 1;
+       } else {
+               /* reading from device with multiple pages */
+               ioctl_exec.iie_cmd[0] = ((memaddr >> 8) & 0xff);
+               ioctl_exec.iie_cmd[1] = (memaddr & 0xff);
+               ioctl_exec.iie_cmdlen = 2;
+       }
        ioctl_exec.iie_buflen = buflen;
 
        r = ioctl(fd, MINIX_I2C_IOCTL_EXEC, &ioctl_exec);
@@ -70,7 +77,7 @@ __eeprom_read32(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)
+    size_t buflen, int flags)
 {
        int r;
        uint16_t i;
@@ -80,10 +87,11 @@ eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
                return -1;
        }
 
-       for (i = 0; i < buflen; i += 32) {
 
-               r = __eeprom_read32(fd, addr, memaddr + i, buf + i,
-                   ((buflen - i) < 32) ? (buflen - i) : 32);
+       for (i = 0; i < buflen; i += 128) {
+
+               r = __eeprom_read128(fd, addr, memaddr + i, buf + i,
+                   ((buflen - i) < 128) ? (buflen - i) : 128, flags);
                if (r == -1) {
                        return -1;
                }
@@ -96,14 +104,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)
+eeprom_dump(int fd, i2c_addr_t addr, int flags)
 {
        int i, j, r;
        uint8_t buf[256];
 
        memset(buf, '\0', 256);
 
-       r = eeprom_read(fd, addr, 0x0000, buf, 256);
+       r = eeprom_read(fd, addr, 0x0000, buf, 256, flags);
        if (r == -1) {
                return r;
        }
@@ -152,13 +160,13 @@ int
 main(int argc, char *argv[])
 {
        int r, fd;
-       int ch, iflag = 0;
+       int ch, iflag = 0, read_flags = 0;
        char *device = DEFAULT_I2C_DEVICE;
        i2c_addr_t address = DEFAULT_I2C_ADDRESS;
 
        setprogname(*argv);
 
-       while ((ch = getopt(argc, argv, "a:f:i")) != -1) {
+       while ((ch = getopt(argc, argv, "a:f:in")) != -1) {
                switch (ch) {
                case 'a':
                        address = strtol(optarg, NULL, 0x10);
@@ -169,6 +177,9 @@ main(int argc, char *argv[])
                case 'i':
                        iflag = 1;
                        break;
+               case 'n':
+                       read_flags |= BDEV_NOPAGE;
+                       break;
                default:
                        break;
                }
@@ -181,13 +192,13 @@ main(int argc, char *argv[])
        }
 
        if (iflag == 1) {
-               r = board_info(fd, address);
+               r = board_info(fd, address, read_flags);
                if (r == -1) {
                        fprintf(stderr, "board_info(): %s\n", strerror(errno));
                        return 1;
                }
        } else {
-               r = eeprom_dump(fd, address);
+               r = eeprom_dump(fd, address, read_flags);
                if (r == -1) {
                        fprintf(stderr, "eeprom_dump(): %s\n", strerror(errno));
                        return 1;
index ee04677b5aa16ff7e4e703f7f6c53ab16d2dff8e..733ba2cf3af1d252305a5430b42096895e3ccfba 100644 (file)
@@ -2,7 +2,7 @@
 #define __EEPROMREAD_H
 
 int eeprom_read(int fd, i2c_addr_t addr, uint16_t memaddr, void *buf,
-                                                               size_t buflen);
-int board_info(int fd, i2c_addr_t address);
+                                               size_t buflen, int flags);
+int board_info(int fd, i2c_addr_t address, int flags);
 
 #endif /* __EEPROMREAD_H */
index 70942c5d0f5bd2deedf2cec1c04e8df3ac819f35..b52cb73a80e8bb960126f94cc900a9b1e78f4c00 100644 (file)
@@ -1,4 +1,5 @@
 #include <minix/blockdriver.h>
+#include <minix/com.h>
 #include <minix/drivers.h>
 #include <minix/ds.h>
 #include <minix/i2c.h>
@@ -53,10 +54,10 @@ struct blockdriver cat24c256_tab = {
        .bdr_device = NULL      /* 1 insance per bus, threads not needed */
 };
 
-static int cat24c256_read32(uint16_t memaddr, void *buf, size_t buflen);
-static int cat24c256_read(uint16_t memaddr, void *buf, size_t buflen);
-static int cat24c256_write16(uint16_t memaddr, void *buf, size_t buflen);
-static int cat24c256_write(uint16_t memaddr, void *buf, size_t buflen);
+static int cat24c256_read128(uint16_t memaddr, void *buf, size_t buflen, int flags);
+static int cat24c256_read(uint16_t memaddr, void *buf, size_t buflen, int flags);
+static int cat24c256_write16(uint16_t memaddr, void *buf, size_t buflen, int flags);
+static int cat24c256_write(uint16_t memaddr, void *buf, size_t buflen, int flags);
 
 /* globals */
 
@@ -176,13 +177,13 @@ cat24c256_blk_transfer(dev_t minor, int do_write, u64_t pos64,
                                return EINVAL;
                        }
 
-                       r = cat24c256_write(position, copybuf, count);
+                       r = cat24c256_write(position, copybuf, count, flags);
                        if (r != OK) {
                                log_warn(&log, "write failed (r=%d)\n", r);
                                return r;
                        }
                } else {
-                       r = cat24c256_read(position, copybuf, count);
+                       r = cat24c256_read(position, copybuf, count, flags);
                        if (r != OK) {
                                log_warn(&log, "read failed (r=%d)\n", r);
                                return r;
@@ -259,16 +260,16 @@ cat24c256_blk_other(message * m)
        return r;
 }
 
-/* The lower level i2c interface can only read/write 32 bytes at a time.
+/* The lower level i2c interface can only read/write 128 bytes at a time.
  * One might want to do more I/O than that at once w/EEPROM, so there is
- * cat24c256_read() and cat24c256_read32(). cat24c256_read32() does the
- * actual reading in chunks up to 32 bytes. cat24c256_read() splits
- * the request up into chunks and repeatedly calls cat24c256_read32()
+ * cat24c256_read() and cat24c256_read128(). cat24c256_read128() does the
+ * actual reading in chunks up to 128 bytes. cat24c256_read() splits
+ * the request up into chunks and repeatedly calls cat24c256_read128()
  * until all of the requested EEPROM locations have been read.
  */
 
 static int
-cat24c256_read32(uint16_t memaddr, void *buf, size_t buflen)
+cat24c256_read128(uint16_t memaddr, void *buf, size_t buflen, int flags)
 {
        int r;
        minix_i2c_ioctl_exec_t ioctl_exec;
@@ -286,9 +287,15 @@ cat24c256_read32(uint16_t memaddr, void *buf, size_t buflen)
        ioctl_exec.iie_addr = address;
 
        /* set the memory address to read from */
-       ioctl_exec.iie_cmd[0] = ((memaddr >> 8) & 0xff);
-       ioctl_exec.iie_cmd[1] = (memaddr & 0xff);
-       ioctl_exec.iie_cmdlen = 2;
+       if ((BDEV_NOPAGE & flags) == BDEV_NOPAGE) {
+               /* reading within the current page */
+               ioctl_exec.iie_cmd[0] = (memaddr & 0xff);
+               ioctl_exec.iie_cmdlen = 1;
+       } else {
+               ioctl_exec.iie_cmd[0] = ((memaddr >> 8) & 0xff);
+               ioctl_exec.iie_cmd[1] = (memaddr & 0xff);
+               ioctl_exec.iie_cmdlen = 2;
+       }
 
        ioctl_exec.iie_buflen = buflen;
 
@@ -307,7 +314,7 @@ cat24c256_read32(uint16_t memaddr, void *buf, size_t buflen)
 }
 
 int
-cat24c256_read(uint16_t memaddr, void *buf, size_t buflen)
+cat24c256_read(uint16_t memaddr, void *buf, size_t buflen, int flags)
 {
        int r;
        uint16_t i;
@@ -317,25 +324,26 @@ cat24c256_read(uint16_t memaddr, void *buf, size_t buflen)
                return -1;
        }
 
-       for (i = 0; i < buflen; i += 32) {
+       for (i = 0; i < buflen; i += 128) {
 
-               r = cat24c256_read32(memaddr + i, buf + i,
-                   ((buflen - i) < 32) ? (buflen - i) : 32);
+               r = cat24c256_read128(memaddr + i, buf + i,
+                   ((buflen - i) < 128) ? (buflen - i) : 128, flags);
                if (r != OK) {
                        return r;
                }
 
                log_trace(&log, "read %d bytes starting at 0x%x\n",
-                   ((buflen - i) < 32) ? (buflen - i) : 32, memaddr + i);
+                   ((buflen - i) < 128) ? (buflen - i) : 128, memaddr + i);
        }
 
        return OK;
 }
 
 static int
-cat24c256_write16(uint16_t memaddr, void *buf, size_t buflen)
+cat24c256_write16(uint16_t memaddr, void *buf, size_t buflen, int flags)
 {
        int r;
+       int addrlen;
        minix_i2c_ioctl_exec_t ioctl_exec;
 
        if (buflen > (I2C_EXEC_MAX_BUFLEN - 2) || buf == NULL
@@ -352,11 +360,17 @@ cat24c256_write16(uint16_t memaddr, void *buf, size_t buflen)
        ioctl_exec.iie_cmdlen = 0;
 
        /* set the memory address to write to */
-       ioctl_exec.iie_buf[0] = ((memaddr >> 8) & 0xff);
-       ioctl_exec.iie_buf[1] = (memaddr & 0xff);
-
-       memcpy(ioctl_exec.iie_buf + 2, buf, buflen);
-       ioctl_exec.iie_buflen = buflen + 2;
+       if ((BDEV_NOPAGE & flags) == BDEV_NOPAGE) {
+               /* writing within the current page */
+               ioctl_exec.iie_buf[0] = (memaddr & 0xff);       /* address */
+               addrlen = 1;
+       } else {
+               ioctl_exec.iie_buf[0] = ((memaddr >> 8) & 0xff);/* page */
+               ioctl_exec.iie_buf[1] = (memaddr & 0xff);       /* address */
+               addrlen = 2;
+       }
+       memcpy(ioctl_exec.iie_buf + addrlen, buf, buflen);
+       ioctl_exec.iie_buflen = buflen + addrlen;
 
        r = i2cdriver_exec(bus_endpoint, &ioctl_exec);
        if (r != OK) {
@@ -371,7 +385,7 @@ cat24c256_write16(uint16_t memaddr, void *buf, size_t buflen)
 }
 
 int
-cat24c256_write(uint16_t memaddr, void *buf, size_t buflen)
+cat24c256_write(uint16_t memaddr, void *buf, size_t buflen, int flags)
 {
        int r;
        uint16_t i;
@@ -384,7 +398,7 @@ cat24c256_write(uint16_t memaddr, void *buf, size_t buflen)
        for (i = 0; i < buflen; i += 16) {
 
                r = cat24c256_write16(memaddr + i, buf + i,
-                   ((buflen - i) < 16) ? (buflen - i) : 16);
+                   ((buflen - i) < 16) ? (buflen - i) : 16, flags);
                if (r != OK) {
                        return r;
                }
index 4cabf816214818004a7900fdf76fbd1b8cd87c9f..9a2994d005e0441f8eec3665ca93af697b2e105e 100644 (file)
 /* Bits in 'BDEV_FLAGS' field of block device transfer requests. */
 #  define BDEV_NOFLAGS         0x00    /* no flags are set */
 #  define BDEV_FORCEWRITE      0x01    /* force write to disk immediately */
+#  define BDEV_NOPAGE          0x02    /* eeprom: don't send page address */
 
 /* Field names for GETRUSAGE related calls */
 #define RU_ENDPT       m1_i1   /* indicates a process for sys_getrusage */
index 52e916eb155f9c068bdab092ae5f4c56157289b6..60af0ea02d7c27007a363011f93fbf9acb5d9c17 100644 (file)
@@ -98,8 +98,8 @@ typedef struct i2c_ioctl_exec {
        void *iie_buf;                  /* pointer to data buffer */
        size_t iie_buflen;              /* length of data buffer */
 } i2c_ioctl_exec_t;
-#define        I2C_EXEC_MAX_CMDLEN     32
-#define        I2C_EXEC_MAX_BUFLEN     32
+#define        I2C_EXEC_MAX_CMDLEN     128
+#define        I2C_EXEC_MAX_BUFLEN     128
 
 #define        I2C_IOCTL_EXEC           _IOW('I', 0, i2c_ioctl_exec_t)