From 8e04a039a9625f75cdc9274ad06c4b8084565848 Mon Sep 17 00:00:00 2001 From: Juergen Borleis Date: Fri, 31 Jul 2015 11:03:52 +0200 Subject: PPC/PCM030: provide EEPROM support to read factory settings Above the 0x800 offset the manufacturer provides the board type, a serial number and the MAC as three simple strings. Extract these strings, provide their value as global variables and set the MAC into the ethernet unit. Signed-off-by: Juergen Borleis Signed-off-by: Sascha Hauer --- arch/ppc/boards/pcm030/Makefile | 2 +- arch/ppc/boards/pcm030/eeprom.c | 118 ++++++++++++++++++++++++++++++++++++++ arch/ppc/boards/pcm030/pcm030.c | 13 +++++ arch/ppc/configs/pcm030_defconfig | 3 + 4 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 arch/ppc/boards/pcm030/eeprom.c (limited to 'arch') diff --git a/arch/ppc/boards/pcm030/Makefile b/arch/ppc/boards/pcm030/Makefile index e7d744bfb4..4e5dc4f57b 100644 --- a/arch/ppc/boards/pcm030/Makefile +++ b/arch/ppc/boards/pcm030/Makefile @@ -1,2 +1,2 @@ -obj-y += pcm030.o +obj-y += pcm030.o eeprom.o extra-y += barebox.lds diff --git a/arch/ppc/boards/pcm030/eeprom.c b/arch/ppc/boards/pcm030/eeprom.c new file mode 100644 index 0000000000..aa00f361cd --- /dev/null +++ b/arch/ppc/boards/pcm030/eeprom.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2015 Juergen Borleis + * + * Based on code from: + * Copyright (C) 2013 Jan Luebbe + * + * 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 + * (at your option) 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCM030_EEPROM_DEVICE "/dev/eeprom0" + +/* + * The first 2048 bytes contain the U-Boot environment shipped with the boards. + * After that an area begins where some board specific and partially unique data + * is stored. All of this data is plain test, string delimiter is the semicolon. + * the last string terminates with a '\0'. + * One example found in the 'product' area: PCM-030-02REI;017822;0050C2875974\0 + * The first string seems to be the product type, the second string some kind + * of serial number and the last string the boards unique MAC. + */ +struct pcm030_eeprom { + char env[0x800]; /* u-boot environment */ + char product[0x80]; /* ;;\0 */ +} __attribute__((packed)); + +static void pcm030_read_factory_data(const struct pcm030_eeprom *buf) +{ + unsigned u, l; + char *board, *serial; + char *full_mac = "xx:xx:xx:xx:xx:xx"; + u8 enetaddr[6]; + + u = 0; + + for (l = 0; (l + u) < sizeof(buf->product); l++) { + if (buf->product[u + l] != ';') + continue; + board = xstrndup(&buf->product[u], l); + u += l + 1; + globalvar_add_simple("model.type", board); + free(board); + } + + for (l = 0; (l + u) < sizeof(buf->product); l++) { + if (buf->product[u + l] != ';') + continue; + serial = xstrndup(&buf->product[u], l); + u += l + 1; + globalvar_add_simple("model.serial", serial); + free(serial); + } + + /* for the MAC do a simple duck test */ + if (buf->product[u] != ';' && buf->product[u + 12] == '\0') { + full_mac[0] = buf->product[u + 0]; + full_mac[1] = buf->product[u + 1]; + full_mac[3] = buf->product[u + 2]; + full_mac[4] = buf->product[u + 3]; + full_mac[6] = buf->product[u + 4]; + full_mac[7] = buf->product[u + 5]; + full_mac[9] = buf->product[u + 6]; + full_mac[10] = buf->product[u + 7]; + full_mac[12] = buf->product[u + 8]; + full_mac[13] = buf->product[u + 9]; + full_mac[15] = buf->product[u + 10]; + full_mac[16] = buf->product[u + 11]; + string_to_ethaddr(full_mac, enetaddr); + eth_register_ethaddr(0, enetaddr); + return; + } + + printf("EEPROM contains no ethernet MAC\n"); +} + +static int pcm030_eeprom_read(void) +{ + int fd, ret; + struct pcm030_eeprom *buf; + + fd = open(PCM030_EEPROM_DEVICE, O_RDONLY); + if (fd < 0) { + perror("failed to open " PCM030_EEPROM_DEVICE); + return fd; + } + + buf = xmalloc(sizeof(struct pcm030_eeprom)); + + ret = pread(fd, buf, sizeof(struct pcm030_eeprom), 0); + if (ret < sizeof(struct pcm030_eeprom)) { + perror("failed to read " PCM030_EEPROM_DEVICE); + goto out; + } + + pcm030_read_factory_data(buf); + ret = 0; +out: + free(buf); + close(fd); + + return ret; +} +late_initcall(pcm030_eeprom_read); diff --git a/arch/ppc/boards/pcm030/pcm030.c b/arch/ppc/boards/pcm030/pcm030.c index fe0f046f4e..11b3beb20f 100644 --- a/arch/ppc/boards/pcm030/pcm030.c +++ b/arch/ppc/boards/pcm030/pcm030.c @@ -34,11 +34,21 @@ #include #include #include +#include static struct fec_platform_data fec_info = { .xcv_type = PHY_INTERFACE_MODE_MII, }; +static struct i2c_board_info pcm030_i2c_devices[] = { + { I2C_BOARD_INFO("pcf8563", 0x51), }, + { I2C_BOARD_INFO("24c32", 0x52), }, +}; + +struct i2c_platform_data pcm030_i2c_plat = { + .bitrate = 100000, +}; + static int devices_init (void) { struct stat s; @@ -53,6 +63,9 @@ static int devices_init (void) add_generic_device("fec_mpc5xxx", DEVICE_ID_DYNAMIC, NULL, MPC5XXX_FEC, 0x200, IORESOURCE_MEM, &fec_info); + i2c_register_board_info(0, pcm030_i2c_devices, ARRAY_SIZE(pcm030_i2c_devices)); + add_generic_device("i2c-fsl", DEVICE_ID_DYNAMIC, NULL, MPC5XXX_I2C2, 0x100, + IORESOURCE_MEM, &pcm030_i2c_plat); ret = stat("/dev/nor0", &s); if (ret) diff --git a/arch/ppc/configs/pcm030_defconfig b/arch/ppc/configs/pcm030_defconfig index 7b84e2f3b6..61380ac294 100644 --- a/arch/ppc/configs/pcm030_defconfig +++ b/arch/ppc/configs/pcm030_defconfig @@ -35,8 +35,11 @@ CONFIG_CMD_OFTREE=y CONFIG_CMD_TIME=y CONFIG_NET=y CONFIG_DRIVER_NET_MPC5200=y +CONFIG_I2C=y +CONFIG_I2C_IMX=y CONFIG_MTD=y CONFIG_DRIVER_CFI=y CONFIG_CFI_BUFFER_WRITE=y +CONFIG_EEPROM_AT24=y CONFIG_FS_TFTP=y CONFIG_ZLIB=y -- cgit v1.2.3