From 9c0fe83eb58ed9cb9faa17646719240abe55f4bf Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Thu, 7 Aug 2014 22:35:45 -0700 Subject: [PATCH] imx: ventana: add econfig command The Gateworks Ventana EEPROM contains a set of configuration bits that affect the removal of device-tree nodes that support peripherals that do not exist on sub-loaded boards. This patch adds: - a structure to define a config bit name, dt node alias, bit position - an array of supported configuration items - an econfig command to get/set/list configuration bits - use of the array when adjusting the FDT prior to boot Signed-off-by: Tim Harvey --- board/gateworks/gw_ventana/eeprom.c | 168 +++++++++++++++++++- board/gateworks/gw_ventana/gw_ventana.c | 100 +++--------- board/gateworks/gw_ventana/ventana_eeprom.h | 11 ++ include/configs/gw_ventana.h | 5 +- 4 files changed, 198 insertions(+), 86 deletions(-) diff --git a/board/gateworks/gw_ventana/eeprom.c b/board/gateworks/gw_ventana/eeprom.c index e90186ebe8..3edc9151d9 100644 --- a/board/gateworks/gw_ventana/eeprom.c +++ b/board/gateworks/gw_ventana/eeprom.c @@ -6,7 +6,10 @@ */ #include +#include #include +#include +#include #include "gsc.h" #include "ventana_eeprom.h" @@ -38,14 +41,12 @@ read_eeprom(int bus, struct ventana_board_info *info) /* read eeprom config section */ if (gsc_i2c_read(GSC_EEPROM_ADDR, 0x00, 1, buf, sizeof(*info))) { puts("EEPROM: Failed to read EEPROM\n"); - info->model[0] = 0; return GW_UNKNOWN; } /* sanity checks */ if (info->model[0] != 'G' || info->model[1] != 'W') { puts("EEPROM: Invalid Model in EEPROM\n"); - info->model[0] = 0; return GW_UNKNOWN; } @@ -55,7 +56,6 @@ read_eeprom(int bus, struct ventana_board_info *info) if ((info->chksum[0] != chksum>>8) || (info->chksum[1] != (chksum&0xff))) { puts("EEPROM: Failed EEPROM checksum\n"); - info->model[0] = 0; return GW_UNKNOWN; } @@ -87,3 +87,165 @@ read_eeprom(int bus, struct ventana_board_info *info) } return type; } + +/* list of config bits that the bootloader will remove from dtb if not set */ +struct ventana_eeprom_config econfig[] = { + { "eth0", "ethernet0", EECONFIG_ETH0 }, + { "eth1", "ethernet1", EECONFIG_ETH1 }, + { "sata", "ahci0", EECONFIG_SATA }, + { "pcie", NULL, EECONFIG_PCIE}, + { "lvds0", NULL, EECONFIG_LVDS0 }, + { "lvds1", NULL, EECONFIG_LVDS1 }, + { "usb0", NULL, EECONFIG_USB0 }, + { "usb1", NULL, EECONFIG_USB1 }, + { "mmc0", NULL, EECONFIG_SD0 }, + { "mmc1", NULL, EECONFIG_SD1 }, + { "mmc2", NULL, EECONFIG_SD2 }, + { "mmc3", NULL, EECONFIG_SD3 }, + { "uart0", NULL, EECONFIG_UART0 }, + { "uart1", NULL, EECONFIG_UART1 }, + { "uart2", NULL, EECONFIG_UART2 }, + { "uart3", NULL, EECONFIG_UART3 }, + { "uart4", NULL, EECONFIG_UART4 }, + { "ipu0", NULL, EECONFIG_IPU0 }, + { "ipu1", NULL, EECONFIG_IPU1 }, + { "can0", NULL, EECONFIG_FLEXCAN }, + { "i2c0", NULL, EECONFIG_I2C0 }, + { "i2c1", NULL, EECONFIG_I2C1 }, + { "i2c2", NULL, EECONFIG_I2C2 }, + { "vpu", NULL, EECONFIG_VPU }, + { "csi0", NULL, EECONFIG_CSI0 }, + { "csi1", NULL, EECONFIG_CSI1 }, + { "spi0", NULL, EECONFIG_ESPCI0 }, + { "spi1", NULL, EECONFIG_ESPCI1 }, + { "spi2", NULL, EECONFIG_ESPCI2 }, + { "spi3", NULL, EECONFIG_ESPCI3 }, + { "spi4", NULL, EECONFIG_ESPCI4 }, + { "spi5", NULL, EECONFIG_ESPCI5 }, + { "gps", "pps", EECONFIG_GPS }, + { "hdmi_in", NULL, EECONFIG_HDMI_IN }, + { "hdmi_out", NULL, EECONFIG_HDMI_OUT }, + { "cvbs_in", NULL, EECONFIG_VID_IN }, + { "cvbs_out", NULL, EECONFIG_VID_OUT }, + { "nand", NULL, EECONFIG_NAND }, + { /* Sentinel */ } +}; + +#ifdef CONFIG_CMD_EECONFIG +static struct ventana_eeprom_config *get_config(const char *name) +{ + struct ventana_eeprom_config *cfg = econfig; + + while (cfg->name) { + if (0 == strcmp(name, cfg->name)) + return cfg; + cfg++; + } + return NULL; +} + +static u8 econfig_bytes[sizeof(ventana_info.config)]; +static int econfig_init = -1; + +int do_econfig(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + struct ventana_eeprom_config *cfg; + struct ventana_board_info *info = &ventana_info; + int i; + + if (argc < 2) + return CMD_RET_USAGE; + + /* initialize */ + if (econfig_init != 1) { + memcpy(econfig_bytes, info->config, sizeof(econfig_bytes)); + econfig_init = 1; + } + + /* list configs */ + if ((strncmp(argv[1], "list", 4) == 0)) { + cfg = econfig; + while (cfg->name) { + printf("%s: %d\n", cfg->name, + test_bit(cfg->bit, econfig_bytes) ? 1 : 0); + cfg++; + } + } + + /* save */ + else if ((strncmp(argv[1], "save", 4) == 0)) { + unsigned char *buf = (unsigned char *)info; + int chksum; + + /* calculate new checksum */ + memcpy(info->config, econfig_bytes, sizeof(econfig_bytes)); + for (chksum = 0, i = 0; i < sizeof(*info)-2; i++) + chksum += buf[i]; + debug("old chksum:0x%04x\n", + (info->chksum[0] << 8) | info->chksum[1]); + debug("new chksum:0x%04x\n", chksum); + info->chksum[0] = chksum >> 8; + info->chksum[1] = chksum & 0xff; + + /* write new config data */ + if (gsc_i2c_write(GSC_EEPROM_ADDR, info->config - (u8 *)info, + 1, econfig_bytes, sizeof(econfig_bytes))) { + printf("EEPROM: Failed updating config\n"); + return CMD_RET_FAILURE; + } + + /* write new config data */ + if (gsc_i2c_write(GSC_EEPROM_ADDR, info->chksum - (u8 *)info, + 1, info->chksum, 2)) { + printf("EEPROM: Failed updating checksum\n"); + return CMD_RET_FAILURE; + } + + printf("Config saved to EEPROM\n"); + } + + /* get config */ + else if (argc == 2) { + cfg = get_config(argv[1]); + if (cfg) { + printf("%s: %d\n", cfg->name, + test_bit(cfg->bit, econfig_bytes) ? 1 : 0); + } else { + printf("invalid config: %s\n", argv[1]); + return CMD_RET_FAILURE; + } + } + + /* set config */ + else if (argc == 3) { + cfg = get_config(argv[1]); + if (cfg) { + if (simple_strtol(argv[2], NULL, 10)) { + test_and_set_bit(cfg->bit, econfig_bytes); + printf("Enabled %s\n", cfg->name); + } else { + test_and_clear_bit(cfg->bit, econfig_bytes); + printf("Disabled %s\n", cfg->name); + } + } else { + printf("invalid config: %s\n", argv[1]); + return CMD_RET_FAILURE; + } + } + + else + return CMD_RET_USAGE; + + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + econfig, 3, 0, do_econfig, + "EEPROM configuration", + "list - list config\n" + "save - save config to EEPROM\n" + " - get config 'name'\n" + " [0|1] - set config 'name' to value\n" +); + +#endif /* CONFIG_CMD_EECONFIG */ diff --git a/board/gateworks/gw_ventana/gw_ventana.c b/board/gateworks/gw_ventana/gw_ventana.c index 2915b9057f..a222921978 100644 --- a/board/gateworks/gw_ventana/gw_ventana.c +++ b/board/gateworks/gw_ventana/gw_ventana.c @@ -50,10 +50,6 @@ DECLARE_GLOBAL_DATA_PTR; #define GP_RS232_EN IMX_GPIO_NR(2, 11) #define GP_MSATA_SEL IMX_GPIO_NR(2, 8) -/* I2C bus numbers */ -#define I2C_GSC 0 -#define I2C_PMIC 1 - #define UART_PAD_CTRL (PAD_CTL_PKE | PAD_CTL_PUE | \ PAD_CTL_PUS_100K_UP | PAD_CTL_SPEED_MED | \ PAD_CTL_DSE_40ohm | PAD_CTL_SRE_FAST | PAD_CTL_HYS) @@ -89,7 +85,7 @@ DECLARE_GLOBAL_DATA_PTR; * EEPROM board info struct populated by read_eeprom so that we only have to * read it once. */ -static struct ventana_board_info ventana_info; +struct ventana_board_info ventana_info; int board_type; @@ -922,7 +918,7 @@ int power_init_board(void) /* configure PFUZE100 PMIC */ if (board_type == GW54xx || board_type == GW54proto) { - power_pfuze100_init(I2C_PMIC); + power_pfuze100_init(CONFIG_I2C_PMIC); p = pmic_get("PFUZE100"); if (p && !pmic_probe(p)) { pmic_reg_read(p, PFUZE100_DEVICEID, ®); @@ -944,7 +940,7 @@ int power_init_board(void) /* configure LTC3676 PMIC */ else { - power_ltc3676_init(I2C_PMIC); + power_ltc3676_init(CONFIG_I2C_PMIC); p = pmic_get("LTC3676_PMIC"); if (p && !pmic_probe(p)) { puts("PMIC: LTC3676\n"); @@ -1175,7 +1171,7 @@ int board_init(void) setup_sata(); #endif /* read Gateworks EEPROM into global struct (used later) */ - board_type = read_eeprom(I2C_GSC, &ventana_info); + board_type = read_eeprom(CONFIG_I2C_GSC, &ventana_info); /* board-specifc GPIO iomux */ SETUP_IOMUX_PADS(gw_gpio_pads); @@ -1223,7 +1219,7 @@ int checkboard(void) return 0; /* Display GSC firmware revision/CRC/status */ - i2c_set_bus_num(I2C_GSC); + i2c_set_bus_num(CONFIG_I2C_GSC); if (!gsc_i2c_read(GSC_SC_ADDR, GSC_SC_FWVER, 1, buf, 1)) { printf("GSC: v%d", buf[0]); if (!gsc_i2c_read(GSC_SC_ADDR, GSC_SC_STATUS, 1, buf, 4)) { @@ -1353,7 +1349,7 @@ int misc_init_r(void) * * Disable the boot watchdog and display/clear the timeout flag if set */ - i2c_set_bus_num(I2C_GSC); + i2c_set_bus_num(CONFIG_I2C_GSC); if (!gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, ®, 1)) { reg |= (1 << GSC_SC_CTRL1_WDDIS); if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, ®, 1)) @@ -1374,74 +1370,6 @@ int misc_init_r(void) #if defined(CONFIG_OF_LIBFDT) && defined(CONFIG_OF_BOARD_SETUP) -/* FDT aliases associated with EEPROM config bits */ -const char *fdt_aliases[] = { - "ethernet0", - "ethernet1", - "hdmi_out", - "ahci0", - "pcie", - "ssi0", - "ssi1", - "lcd0", - "lvds0", - "lvds1", - "usb0", - "usb1", - "mmc0", - "mmc1", - "mmc2", - "mmc3", - "uart0", - "uart1", - "uart2", - "uart3", - "uart4", - "ipu0", - "ipu1", - "can0", - "mipi_dsi", - "mipi_csi", - "tzasc0", - "tzasc1", - "i2c0", - "i2c1", - "i2c2", - "vpu", - "csi0", - "csi1", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - "spi0", - "spi1", - "spi2", - "spi3", - "spi4", - "spi5", - NULL, - NULL, - "pps", - NULL, - NULL, - NULL, - "hdmi_in", - "cvbs_out", - "cvbs_in", - "nand", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, -}; - /* * called prior to booting kernel or by 'fdt boardsetup' command * @@ -1453,8 +1381,8 @@ const char *fdt_aliases[] = { */ void ft_board_setup(void *blob, bd_t *bd) { - int bit; struct ventana_board_info *info = &ventana_info; + struct ventana_eeprom_config *cfg; struct node_info nodes[] = { { "sst,w25q256", MTD_DEV_TYPE_NOR, }, /* SPI flash */ { "fsl,imx6q-gpmi-nand", MTD_DEV_TYPE_NAND, }, /* NAND flash */ @@ -1489,9 +1417,17 @@ void ft_board_setup(void *blob, bd_t *bd) * remove nodes by alias path if EEPROM config tells us the * peripheral is not loaded on the board. */ - for (bit = 0; bit < 64; bit++) { - if (!test_bit(bit, info->config)) - fdt_del_node_and_alias(blob, fdt_aliases[bit]); + if (getenv("fdt_noconfig")) { + puts(" Skiping periperhal config (fdt_noconfig defined)\n"); + return; + } + cfg = econfig; + while (cfg->name) { + if (!test_bit(cfg->bit, info->config)) { + fdt_del_node_and_alias(blob, cfg->dtalias ? + cfg->dtalias : cfg->name); + } + cfg++; } } #endif /* defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) */ diff --git a/board/gateworks/gw_ventana/ventana_eeprom.h b/board/gateworks/gw_ventana/ventana_eeprom.h index 5b065bea4e..d64b9107c6 100644 --- a/board/gateworks/gw_ventana/ventana_eeprom.h +++ b/board/gateworks/gw_ventana/ventana_eeprom.h @@ -110,8 +110,19 @@ enum { GW53xx, GW54xx, GW_UNKNOWN, + GW_BADCRC, }; +/* config items */ +struct ventana_eeprom_config { + const char *name; /* name of item */ + const char *dtalias; /* name of dt node to remove if not set */ + int bit; /* bit within config */ +}; + +extern struct ventana_eeprom_config econfig[]; +extern struct ventana_board_info ventana_info; + int read_eeprom(int bus, struct ventana_board_info *); #endif diff --git a/include/configs/gw_ventana.h b/include/configs/gw_ventana.h index 8197a72674..b991b093cb 100644 --- a/include/configs/gw_ventana.h +++ b/include/configs/gw_ventana.h @@ -95,7 +95,9 @@ #define CONFIG_CMD_I2C #define CONFIG_SYS_I2C #define CONFIG_SYS_I2C_MXC -#define CONFIG_SYS_I2C_SPEED 100000 +#define CONFIG_SYS_I2C_SPEED 100000 +#define CONFIG_I2C_GSC 0 +#define CONFIG_I2C_PMIC 1 /* MMC Configs */ #define CONFIG_FSL_ESDHC @@ -164,6 +166,7 @@ #define CONFIG_CMD_SETEXPR #define CONFIG_CMD_BOOTZ #define CONFIG_CMD_GSC +#define CONFIG_CMD_EECONFIG /* Gateworks EEPROM config cmd */ #define CONFIG_CMD_UBI #define CONFIG_RBTREE #define CONFIG_LZO -- 2.39.5