/* * Copyright (c) 2014 Sulev-Madis Silber * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * * ORIGINAL CODE: * * bbb_sysutil.c Beaglebone Black System Utility * * Compile with: * cc bbb_sysutil.c -o bbb_sysutil * * Winston Smith */ #include #include #include #include #include #include #include #include #include #define MIN(a,b) ((a) < (b) ? (a) : (b)) /* * BeagleBone Black system EEPROM signature */ uint8_t signature[] = { 0xAA, 0x55, 0x33, 0xEE }; typedef struct { int value; char *name; } KV; static KV TPS65217_ID[] = { { 0b01100000, "TPS65217D" }, { 0b01110000, "TPS65217A" }, { 0b11100000, "TPS65217C" }, { 0b11110000, "TPS65217B" }, { 0, 0 }, }; static KV TPS65217_STATUS[] = { { 0b1000, "ACPWR" }, { 0b0100, "USBPWR" }, { 0, 0 }, }; size_t KV_lookup_value(int val, KV *table, char *buffer, size_t max) { int i; for (i = 0; table[i].name; i++) { if (val == table[i].value) { size_t sz = MIN(max-1, strlen(table[i].name)); strncpy(buffer, table[i].name, sz); buffer[sz] = 0; return sz; } } return 0; } size_t KV_lookup_mask(int mask, KV *table, char *buffer, size_t max) { int i; size_t used = 0; buffer[0] = 0; for (i = 0; table[i].name; i++) { if ((mask & table[i].value) != 0) { size_t sz = MIN(max - used - 1, strlen(table[i].name) + (used > 0 ? 1 : 0)); if ((used > 0) && (sz > 0)) { strcat(buffer, "|"); used++; sz--; } strncat(buffer, table[i].name, sz); used += sz; } } return used; } /* * Read data from an i2c device */ int i2c_read(int fd, int slave, uint8_t *buffer, uint16_t offset, uint16_t offsetlen, uint16_t max) { struct iic_msg msg[2]; struct iic_rdwr_data rdwr; slave = slave << 1; msg[0].slave = slave; msg[0].flags = IIC_M_WR; msg[0].len = offsetlen; msg[0].buf = (uint8_t*)&offset; msg[1].slave = slave; msg[1].flags = IIC_M_RD; msg[1].len = max; msg[1].buf = buffer; rdwr.nmsgs = 2; rdwr.msgs = msg; if (ioctl(fd, I2CRDWR, &rdwr) < 0) { return errno; } return 0; } /* * Read data from the Beaglebone system EEPROM */ int read_eeprom(int fd) { int addr = 0x50; int err; uint8_t buffer[28]; char work[32]; // For sanity checking! memset((void*)buffer, '@', sizeof(buffer)); if ((err = i2c_read(fd, addr, buffer, 0, sizeof(uint16_t), sizeof(buffer))) != 0) { fprintf(stderr, "ERROR: read_eeprom() (@ address %02X): i2c_read() failed with: %s (%d)\n", addr, strerror(err), err); return 1; } if (memcmp((void*)buffer, (void*)signature, sizeof(signature)) != 0) { fprintf(stderr, "ERROR: EEPROM (@ address %02X) signature mismatched (%02X:%02X:%02X:%02X)\n", addr, buffer[0], buffer[1], buffer[2], buffer[3]); return 1; } printf(" eeprom_address=%02X eeprom_signature=%02X:%02X:%02X:%02X", addr, buffer[0], buffer[1], buffer[2], buffer[3]); // Extract the 12 bytes allocated to the model strncpy(work, (char*)&buffer[4], 12); work[12] = 0; printf(" eeprom_model=%s", work); // Extract the 12 bytes allocated to the serial number strncpy(work, (char*)&buffer[16], 12); work[12] = 0; printf(" eeprom_serial=%s", work); return 0; } /* * Read data from the Beaglebone system PMIC */ int read_pmic(int fd) { int addr = 0x24; int err; uint8_t chipid; uint8_t status; char work[32]; if ((err = i2c_read(fd, addr, &chipid, 0, sizeof(uint8_t), sizeof(chipid))) != 0) { fprintf(stderr, "ERROR: read_pmic() (TPS65217 PMIC @ address %02X): i2c_read() failed with: %s (%d)\n", addr, strerror(err), err); return 1; } if ((err = i2c_read(fd, addr, &status, 0x0A, sizeof(uint8_t), sizeof(status))) != 0) { fprintf(stderr, "ERROR: read_pmic() (TPS65217 PMIC @ address %02X): i2c_read() failed with: %s (%d)\n", addr, strerror(err), err); return 1; } printf(" pmic_address=%02X", addr); KV_lookup_value(chipid & 0xF0, TPS65217_ID, work, sizeof(work)); printf(" pmic_chipid=%02X,%s-rev-1.%d", chipid, work, chipid & 0xF); KV_lookup_mask(status, TPS65217_STATUS, work, sizeof(work)); printf(" pmic_status=%02X,%s", status, work); return 0; } int main(int argc, char **argv) { int fd = -1; int err = 0; char *dev = "/dev/iic0"; char buf[32]; if (argc > 1) { dev = argv[1]; } if ((fd = open(dev, O_RDWR)) < 0) { perror("open failed"); err = 1; goto exit; } while (1) { scanf("%1s", buf); printf("i2c"); read_pmic(fd); read_eeprom(fd); printf("\n"); fflush(stdout); } exit: if (fd != -1) { close(fd); } exit(err); }