@@ -227,6 +227,8 @@ config TARGET_GW_VENTANA
bool "gw_ventana"
depends on MX6QDL
select SUPPORT_SPL
+ select GATEWORKS_SC
+ select MISC
imply CMD_SATA
imply CMD_SPL
@@ -17,12 +17,4 @@ config CMD_EECONFIG
help
Provides access to EEPROM configuration on Gateworks Ventana
-config CMD_GSC
- bool "Enable the 'gsc' command"
- help
- Provides access to the GSC configuration:
-
- gsc sleep - sleeps for a period of seconds
- gsc wd - enables / disables the watchdog
-
endif
@@ -6,5 +6,5 @@
# SPDX-License-Identifier: GPL-2.0+
#
-obj-y := gw_ventana.o gsc.o eeprom.o common.o
+obj-y := gw_ventana.o eeprom.o common.o
obj-$(CONFIG_SPL_BUILD) += gw_ventana_spl.o
@@ -6,15 +6,15 @@
*/
#include <common.h>
+#include <env.h>
+#include <fsl_esdhc_imx.h>
+#include <hwconfig.h>
#include <log.h>
#include <asm/arch/clock.h>
#include <asm/arch/mx6-pins.h>
#include <asm/arch/sys_proto.h>
#include <asm/gpio.h>
#include <asm/mach-imx/mxc_i2c.h>
-#include <env.h>
-#include <fsl_esdhc_imx.h>
-#include <hwconfig.h>
#include <linux/delay.h>
#include "common.h"
@@ -1045,7 +1045,7 @@ struct ventana gpio_cfg[GW_UNKNOWN] = {
#define SETUP_GPIO_INPUT(gpio, name) \
gpio_request(gpio, name); \
gpio_direction_input(gpio);
-void setup_iomux_gpio(int board, struct ventana_board_info *info)
+void setup_iomux_gpio(int board)
{
if (board >= GW_UNKNOWN)
return;
@@ -1214,8 +1214,6 @@ static struct fsl_esdhc_cfg usdhc_cfg[2];
int board_mmc_init(struct bd_info *bis)
{
- struct ventana_board_info ventana_info;
- int board_type = read_eeprom(CONFIG_I2C_GSC, &ventana_info);
int ret;
switch (board_type) {
@@ -1279,13 +1277,11 @@ int board_mmc_init(struct bd_info *bis)
int board_mmc_getcd(struct mmc *mmc)
{
- struct ventana_board_info ventana_info;
struct fsl_esdhc_cfg *cfg = (struct fsl_esdhc_cfg *)mmc->priv;
- int board = read_eeprom(CONFIG_I2C_GSC, &ventana_info);
- int gpio = gpio_cfg[board].mmc_cd;
+ int gpio = gpio_cfg[board_type].mmc_cd;
/* Card Detect */
- switch (board) {
+ switch (board_type) {
case GW560x:
/* emmc is always present */
if (cfg->esdhc_base == USDHC2_BASE_ADDR)
@@ -8,7 +8,7 @@
#ifndef _GWVENTANA_COMMON_H_
#define _GWVENTANA_COMMON_H_
-#include "ventana_eeprom.h"
+#include "eeprom.h"
/* GPIO's common to all baseboards */
#define GP_RS232_EN IMX_GPIO_NR(2, 11)
@@ -80,6 +80,6 @@ struct ventana {
extern struct ventana gpio_cfg[GW_UNKNOWN];
/* configure gpio iomux/defaults */
-void setup_iomux_gpio(int board, struct ventana_board_info *);
+void setup_iomux_gpio(int board);
#endif /* #ifndef _GWVENTANA_COMMON_H_ */
@@ -4,23 +4,211 @@
* Author: Tim Harvey <tharvey@gateworks.com>
*/
-#include <common.h>
#include <command.h>
-#include <errno.h>
+#include <common.h>
+#include <gsc.h>
#include <hexdump.h>
#include <i2c.h>
-#include <log.h>
-#include <malloc.h>
-#include <asm/bitops.h>
-#include <linux/delay.h>
+#include <asm/arch/sys_proto.h>
+#include <dm/device.h>
#include <dm/uclass.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+
+#include "eeprom.h"
+
+/*
+ * EEPROM board info struct populated by read_eeprom so that we only have to
+ * read it once.
+ */
+struct ventana_board_info ventana_info;
+int board_type;
+
+#if CONFIG_IS_ENABLED(DM_I2C)
+struct udevice *i2c_get_dev(int busno, int slave)
+{
+ struct udevice *dev, *bus;
+ int ret;
+
+ ret = uclass_get_device_by_seq(UCLASS_I2C, busno, &bus);
+ if (ret)
+ return NULL;
+ ret = dm_i2c_probe(bus, slave, 0, &dev);
+ if (ret)
+ return NULL;
+
+ return dev;
+}
+#endif
+
+/*
+ * The Gateworks System Controller will fail to ACK a master transaction if
+ * it is busy, which can occur during its 1HZ timer tick while reading ADC's.
+ * When this does occur, it will never be busy long enough to fail more than
+ * 2 back-to-back transfers. Thus we wrap i2c_read and i2c_write with
+ * 3 retries.
+ */
+int gsc_i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+ int retry = 3;
+ int n = 0;
+ int ret;
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *dev;
+
+ dev = i2c_get_dev(BOARD_EEPROM_BUSNO, chip);
+ if (!dev)
+ return -ENODEV;
+ ret = i2c_set_chip_offset_len(dev, alen);
+ if (ret) {
+ puts("EEPROM: Failed to set alen\n");
+ return ret;
+ }
+#else
+ i2c_set_bus_num(BOARD_EEPROM_BUSNO);
+#endif
+
+ while (n++ < retry) {
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = dm_i2c_read(dev, addr, buf, len);
+#else
+ ret = i2c_read(chip, addr, alen, buf, len);
+#endif
+ if (!ret)
+ break;
+ debug("%s: 0x%02x 0x%02x retry%d: %d\n", __func__, chip, addr,
+ n, ret);
+ if (ret != -ENODEV)
+ break;
+ mdelay(10);
+ }
+ return ret;
+}
+
+int gsc_i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
+{
+ int retry = 3;
+ int n = 0;
+ int ret;
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *dev;
+
+ dev = i2c_get_dev(BOARD_EEPROM_BUSNO, chip);
+ if (!dev)
+ return -ENODEV;
+ ret = i2c_set_chip_offset_len(dev, alen);
+ if (ret) {
+ puts("EEPROM: Failed to set alen\n");
+ return ret;
+ }
+#endif
+
+ while (n++ < retry) {
+#if CONFIG_IS_ENABLED(DM_I2C)
+ ret = dm_i2c_write(dev, addr, buf, len);
+#else
+ ret = i2c_write(chip, addr, alen, buf, len);
+#endif
+ if (!ret)
+ break;
+ debug("%s: 0x%02x 0x%02x retry%d: %d\n", __func__, chip, addr,
+ n, ret);
+ if (ret != -ENODEV)
+ break;
+ mdelay(10);
+ }
+ mdelay(100);
+ return ret;
+}
+
+/* determine BOM revision from model */
+int get_bom_rev(const char *str)
+{
+ int rev_bom = 0;
+ int i;
+
+ for (i = strlen(str) - 1; i > 0; i--) {
+ if (str[i] == '-')
+ break;
+ if (str[i] >= '1' && str[i] <= '9') {
+ rev_bom = str[i] - '0';
+ break;
+ }
+ }
+ return rev_bom;
+}
-#include "gsc.h"
-#include "ventana_eeprom.h"
+/* determine PCB revision from model */
+char get_pcb_rev(const char *str)
+{
+ char rev_pcb = 'A';
+ int i;
+ for (i = strlen(str) - 1; i > 0; i--) {
+ if (str[i] == '-')
+ break;
+ if (str[i] >= 'A') {
+ rev_pcb = str[i];
+ break;
+ }
+ }
+ return rev_pcb;
+}
+
+/*
+ * get dt name based on model and detail level:
+ */
+const char *gsc_get_dtb_name(int level, char *buf, int sz)
+{
+ const char *model = (const char *)ventana_info.model;
+ const char *pre = is_mx6dq() ? "imx6q-" : "imx6dl-";
+ int modelno, rev_pcb, rev_bom;
+
+ /* a few board models are dt equivalents to other models */
+ if (strncasecmp(model, "gw5906", 6) == 0)
+ model = "gw552x-d";
+ else if (strncasecmp(model, "gw5908", 6) == 0)
+ model = "gw53xx-f";
+ else if (strncasecmp(model, "gw5905", 6) == 0)
+ model = "gw5904-a";
+
+ modelno = ((model[2] - '0') * 1000)
+ + ((model[3] - '0') * 100)
+ + ((model[4] - '0') * 10)
+ + (model[5] - '0');
+ rev_pcb = tolower(get_pcb_rev(model));
+ rev_bom = get_bom_rev(model);
+
+ /* compare model/rev/bom in order of most specific to least */
+ snprintf(buf, sz, "%s%04d", pre, modelno);
+ switch (level) {
+ case 0: /* full model first (ie gw5400-a1) */
+ if (rev_bom) {
+ snprintf(buf, sz, "%sgw%04d-%c%d", pre, modelno, rev_pcb, rev_bom);
+ break;
+ }
+ fallthrough;
+ case 1: /* don't care about bom rev (ie gw5400-a) */
+ snprintf(buf, sz, "%sgw%04d-%c", pre, modelno, rev_pcb);
+ break;
+ case 2: /* don't care about the pcb rev (ie gw5400) */
+ snprintf(buf, sz, "%sgw%04d", pre, modelno);
+ break;
+ case 3: /* look for generic model (ie gw540x) */
+ snprintf(buf, sz, "%sgw%03dx", pre, modelno / 10);
+ break;
+ case 4: /* look for more generic model (ie gw54xx) */
+ snprintf(buf, sz, "%sgw%02dxx", pre, modelno / 100);
+ break;
+ default: /* give up */
+ return NULL;
+ }
+
+ return buf;
+}
/* read ventana EEPROM, check for validity, and return baseboard type */
int
-read_eeprom(int bus, struct ventana_board_info *info)
+read_eeprom(struct ventana_board_info *info)
{
int i;
int chksum;
@@ -30,29 +218,8 @@ read_eeprom(int bus, struct ventana_board_info *info)
memset(info, 0, sizeof(*info));
- /*
- * On a board with a missing/depleted backup battery for GSC, the
- * board may be ready to probe the GSC before its firmware is
- * running. We will wait here indefinately for the GSC/EEPROM.
- */
-#if CONFIG_IS_ENABLED(DM_I2C)
- while (1) {
- if (i2c_get_dev(bus, GSC_EEPROM_ADDR))
- break;
- mdelay(1);
- }
-#else
- while (1) {
- if (0 == i2c_set_bus_num(bus) &&
- 0 == i2c_probe(GSC_EEPROM_ADDR))
- break;
- mdelay(1);
- }
-#endif
-
/* read eeprom config section */
- mdelay(10);
- if (gsc_i2c_read(GSC_EEPROM_ADDR, 0x00, 1, buf, sizeof(*info))) {
+ if (gsc_i2c_read(BOARD_EEPROM_ADDR, 0x00, 1, buf, sizeof(*info))) {
puts("EEPROM: Failed to read EEPROM\n");
return GW_UNKNOWN;
}
@@ -219,14 +386,14 @@ static int do_econfig(struct cmd_tbl *cmdtp, int flag, int argc,
info->chksum[1] = chksum & 0xff;
/* write new config data */
- if (gsc_i2c_write(GSC_EEPROM_ADDR, info->config - (u8 *)info,
+ if (gsc_i2c_write(BOARD_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,
+ if (gsc_i2c_write(BOARD_EEPROM_ADDR, info->chksum - (u8 *)info,
1, info->chksum, 2)) {
printf("EEPROM: Failed updating checksum\n");
return CMD_RET_FAILURE;
similarity index 82%
rename from board/gateworks/gw_ventana/ventana_eeprom.h
rename to board/gateworks/gw_ventana/eeprom.h
@@ -6,6 +6,9 @@
#ifndef _VENTANA_EEPROM_
#define _VENTANA_EEPROM_
+#define BOARD_EEPROM_BUSNO 0
+#define BOARD_EEPROM_ADDR 0x51
+
struct ventana_board_info {
u8 mac0[6]; /* 0x00: MAC1 */
u8 mac1[6]; /* 0x06: MAC2 */
@@ -137,7 +140,18 @@ struct ventana_eeprom_config {
extern struct ventana_eeprom_config econfig[];
extern struct ventana_board_info ventana_info;
+extern int board_type;
+
+int read_eeprom(struct ventana_board_info *info);
-int read_eeprom(int bus, struct ventana_board_info *);
+/*
+ * I2C transactions to the GSC are done via these functions which
+ * perform retries in the case of a busy GSC NAK'ing the transaction
+ */
+int gsc_i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len);
+int gsc_i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len);
+const char *gsc_get_dtb_name(int level, char *buf, int sz);
+struct udevice *i2c_get_dev(int busno, int slave);
+const char *eeprom_get_model(void);
#endif
deleted file mode 100644
@@ -1,471 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (C) 2013 Gateworks Corporation
- *
- * Author: Tim Harvey <tharvey@gateworks.com>
- */
-
-#include <common.h>
-#include <command.h>
-#include <log.h>
-#include <linux/delay.h>
-#include <linux/errno.h>
-#include <common.h>
-#include <i2c.h>
-#include <linux/ctype.h>
-
-#include <asm/arch/sys_proto.h>
-#include <asm/global_data.h>
-#include <dm/device.h>
-#include <dm/uclass.h>
-
-#include "ventana_eeprom.h"
-#include "gsc.h"
-
-DECLARE_GLOBAL_DATA_PTR;
-
-#if CONFIG_IS_ENABLED(DM_I2C)
-struct udevice *i2c_get_dev(int busno, int slave)
-{
- struct udevice *dev, *bus;
- int ret;
-
- ret = uclass_get_device_by_seq(UCLASS_I2C, busno, &bus);
- if (ret)
- return NULL;
- ret = dm_i2c_probe(bus, slave, 0, &dev);
- if (ret)
- return NULL;
-
- return dev;
-}
-#endif
-
-/*
- * The Gateworks System Controller will fail to ACK a master transaction if
- * it is busy, which can occur during its 1HZ timer tick while reading ADC's.
- * When this does occur, it will never be busy long enough to fail more than
- * 2 back-to-back transfers. Thus we wrap i2c_read and i2c_write with
- * 3 retries.
- */
-int gsc_i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
-{
- int retry = 3;
- int n = 0;
- int ret;
-#if CONFIG_IS_ENABLED(DM_I2C)
- struct udevice *dev;
-
- dev = i2c_get_dev(CONFIG_I2C_GSC, chip);
- if (!dev)
- return -ENODEV;
- ret = i2c_set_chip_offset_len(dev, alen);
- if (ret) {
- puts("EEPROM: Failed to set alen\n");
- return ret;
- }
-#else
- i2c_set_bus_num(CONFIG_I2C_GSC);
-#endif
-
- while (n++ < retry) {
-#if CONFIG_IS_ENABLED(DM_I2C)
- ret = dm_i2c_read(dev, addr, buf, len);
-#else
- ret = i2c_read(chip, addr, alen, buf, len);
-#endif
- if (!ret)
- break;
- debug("%s: 0x%02x 0x%02x retry%d: %d\n", __func__, chip, addr,
- n, ret);
- if (ret != -ENODEV)
- break;
- mdelay(10);
- }
- return ret;
-}
-
-int gsc_i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
-{
- int retry = 3;
- int n = 0;
- int ret;
-#if CONFIG_IS_ENABLED(DM_I2C)
- struct udevice *dev;
-
- dev = i2c_get_dev(CONFIG_I2C_GSC, chip);
- if (!dev)
- return -ENODEV;
- ret = i2c_set_chip_offset_len(dev, alen);
- if (ret) {
- puts("EEPROM: Failed to set alen\n");
- return ret;
- }
-#endif
-
- while (n++ < retry) {
-#if CONFIG_IS_ENABLED(DM_I2C)
- ret = dm_i2c_write(dev, addr, buf, len);
-#else
- ret = i2c_write(chip, addr, alen, buf, len);
-#endif
- if (!ret)
- break;
- debug("%s: 0x%02x 0x%02x retry%d: %d\n", __func__, chip, addr,
- n, ret);
- if (ret != -ENODEV)
- break;
- mdelay(10);
- }
- mdelay(100);
- return ret;
-}
-
-int gsc_get_board_temp(void)
-{
- const void *fdt = gd->fdt_blob;
- int node, reg, mode, val;
- const char *label;
- u8 buf[2];
- int ret;
-
- node = fdt_node_offset_by_compatible(fdt, -1, "gw,gsc-adc");
- if (node <= 0)
- return node;
-
- /* iterate over hwmon nodes */
- node = fdt_first_subnode(fdt, node);
- while (node > 0) {
- reg = fdtdec_get_int(fdt, node, "reg", -1);
- mode = fdtdec_get_int(fdt, node, "gw,mode", -1);
- label = fdt_stringlist_get(fdt, node, "label", 0, NULL);
-
- if ((reg == -1) || (mode == -1) || !label) {
- printf("invalid dt:%s\n", fdt_get_name(fdt, node, NULL));
- continue;
- }
-
- if ((mode != 0) || strcmp(label, "temp"))
- continue;
-
- memset(buf, 0, sizeof(buf));
- ret = gsc_i2c_read(GSC_HWMON_ADDR, reg, 1, buf, sizeof(buf));
- val = buf[0] | buf[1] << 8;
- if (val >= 0) {
- if (val > 0x8000)
- val -= 0xffff;
- return val;
- }
- node = fdt_next_subnode(fdt, node);
- }
-
- return 0;
-}
-
-/* display hardware monitor ADC channels */
-int gsc_hwmon(void)
-{
- const void *fdt = gd->fdt_blob;
- int node, reg, mode, len, val, offset;
- const char *label;
- u8 buf[2];
- int ret;
-
- node = fdt_node_offset_by_compatible(fdt, -1, "gw,gsc-adc");
- if (node <= 0)
- return node;
-
- /* iterate over hwmon nodes */
- node = fdt_first_subnode(fdt, node);
- while (node > 0) {
- reg = fdtdec_get_int(fdt, node, "reg", -1);
- mode = fdtdec_get_int(fdt, node, "gw,mode", -1);
- offset = fdtdec_get_int(fdt, node, "gw,voltage-offset-microvolt", 0);
- label = fdt_stringlist_get(fdt, node, "label", 0, NULL);
-
- if ((reg == -1) || (mode == -1) || !label)
- printf("invalid dt:%s\n", fdt_get_name(fdt, node, NULL));
-
- memset(buf, 0, sizeof(buf));
- ret = gsc_i2c_read(GSC_HWMON_ADDR, reg, 1, buf, sizeof(buf));
- val = buf[0] | buf[1] << 8;
- if (val >= 0) {
- const u32 *div;
- int r[2];
-
- switch (mode) {
- case 0: /* temperature (C*10) */
- if (val > 0x8000)
- val -= 0xffff;
- printf("%-8s: %d.%ldC\n", label, val / 10, abs(val % 10));
- break;
- case 1: /* prescaled voltage */
- if (val != 0xffff)
- printf("%-8s: %d.%03dV\n", label, val / 1000, val % 1000);
- break;
- case 2: /* scaled based on ref volt and resolution */
- val *= 2500;
- val /= 1 << 12;
-
- /* apply pre-scaler voltage divider */
- div = fdt_getprop(fdt, node, "gw,voltage-divider-ohms", &len);
- if (div && (len == sizeof(uint32_t) * 2)) {
- r[0] = fdt32_to_cpu(div[0]);
- r[1] = fdt32_to_cpu(div[1]);
- if (r[0] && r[1]) {
- val *= (r[0] + r[1]);
- val /= r[1];
- }
- }
-
- /* adjust by offset */
- val += (offset / 1000);
-
- printf("%-8s: %d.%03dV\n", label, val / 1000, val % 1000);
- break;
- }
- }
- node = fdt_next_subnode(fdt, node);
- }
-
- return 0;
-}
-
-int gsc_info(int verbose)
-{
- unsigned char buf[16];
-
- if (gsc_i2c_read(GSC_SC_ADDR, 0, 1, buf, 16))
- return CMD_RET_FAILURE;
-
- printf("GSC: v%d", buf[GSC_SC_FWVER]);
- printf(" 0x%04x", buf[GSC_SC_FWCRC] | buf[GSC_SC_FWCRC+1]<<8);
- printf(" WDT:%sabled", (buf[GSC_SC_CTRL1] & (1<<GSC_SC_CTRL1_WDEN))
- ? "en" : "dis");
- if (buf[GSC_SC_STATUS] & (1 << GSC_SC_IRQ_WATCHDOG)) {
- buf[GSC_SC_STATUS] &= ~(1 << GSC_SC_IRQ_WATCHDOG);
- puts(" WDT_RESET");
- gsc_i2c_write(GSC_SC_ADDR, GSC_SC_STATUS, 1,
- &buf[GSC_SC_STATUS], 1);
- }
- printf(" board temp at %dC", gsc_get_board_temp() / 10);
- puts("\n");
- if (!verbose)
- return CMD_RET_SUCCESS;
-
- gsc_hwmon();
-
- return 0;
-}
-
-/*
- * The Gateworks System Controller implements a boot
- * watchdog (always enabled) as a workaround for IMX6 boot related
- * errata such as:
- * ERR005768 - no fix scheduled
- * ERR006282 - fixed in silicon r1.2
- * ERR007117 - fixed in silicon r1.3
- * ERR007220 - fixed in silicon r1.3
- * ERR007926 - no fix scheduled
- * see http://cache.freescale.com/files/32bit/doc/errata/IMX6DQCE.pdf
- *
- * Disable the boot watchdog
- */
-int gsc_boot_wd_disable(void)
-{
- u8 reg;
-
- 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))
- return 0;
- }
- puts("Error: could not disable GSC Watchdog\n");
- return 1;
-}
-
-/* determine BOM revision from model */
-int get_bom_rev(const char *str)
-{
- int rev_bom = 0;
- int i;
-
- for (i = strlen(str) - 1; i > 0; i--) {
- if (str[i] == '-')
- break;
- if (str[i] >= '1' && str[i] <= '9') {
- rev_bom = str[i] - '0';
- break;
- }
- }
- return rev_bom;
-}
-
-/* determine PCB revision from model */
-char get_pcb_rev(const char *str)
-{
- char rev_pcb = 'A';
- int i;
-
- for (i = strlen(str) - 1; i > 0; i--) {
- if (str[i] == '-')
- break;
- if (str[i] >= 'A') {
- rev_pcb = str[i];
- break;
- }
- }
- return rev_pcb;
-}
-
-/*
- * get dt name based on model and detail level:
- */
-const char *gsc_get_dtb_name(int level, char *buf, int sz)
-{
- const char *model = (const char *)ventana_info.model;
- const char *pre = is_mx6dq() ? "imx6q-" : "imx6dl-";
- int modelno, rev_pcb, rev_bom;
-
- /* a few board models are dt equivalents to other models */
- if (strncasecmp(model, "gw5906", 6) == 0)
- model = "gw552x-d";
- else if (strncasecmp(model, "gw5908", 6) == 0)
- model = "gw53xx-f";
- else if (strncasecmp(model, "gw5905", 6) == 0)
- model = "gw5904-a";
-
- modelno = ((model[2] - '0') * 1000)
- + ((model[3] - '0') * 100)
- + ((model[4] - '0') * 10)
- + (model[5] - '0');
- rev_pcb = tolower(get_pcb_rev(model));
- rev_bom = get_bom_rev(model);
-
- /* compare model/rev/bom in order of most specific to least */
- snprintf(buf, sz, "%s%04d", pre, modelno);
- switch (level) {
- case 0: /* full model first (ie gw5400-a1) */
- if (rev_bom) {
- snprintf(buf, sz, "%sgw%04d-%c%d", pre, modelno, rev_pcb, rev_bom);
- break;
- }
- fallthrough;
- case 1: /* don't care about bom rev (ie gw5400-a) */
- snprintf(buf, sz, "%sgw%04d-%c", pre, modelno, rev_pcb);
- break;
- case 2: /* don't care about the pcb rev (ie gw5400) */
- snprintf(buf, sz, "%sgw%04d", pre, modelno);
- break;
- case 3: /* look for generic model (ie gw540x) */
- snprintf(buf, sz, "%sgw%03dx", pre, modelno / 10);
- break;
- case 4: /* look for more generic model (ie gw54xx) */
- snprintf(buf, sz, "%sgw%02dxx", pre, modelno / 100);
- break;
- default: /* give up */
- return NULL;
- }
-
- return buf;
-}
-
-#if defined(CONFIG_CMD_GSC) && !defined(CONFIG_SPL_BUILD)
-static int do_gsc_sleep(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
-{
- unsigned char reg;
- unsigned long secs = 0;
-
- if (argc < 2)
- return CMD_RET_USAGE;
-
- secs = dectoul(argv[1], NULL);
- printf("GSC Sleeping for %ld seconds\n", secs);
-
- reg = (secs >> 24) & 0xff;
- if (gsc_i2c_write(GSC_SC_ADDR, 9, 1, ®, 1))
- goto error;
- reg = (secs >> 16) & 0xff;
- if (gsc_i2c_write(GSC_SC_ADDR, 8, 1, ®, 1))
- goto error;
- reg = (secs >> 8) & 0xff;
- if (gsc_i2c_write(GSC_SC_ADDR, 7, 1, ®, 1))
- goto error;
- reg = secs & 0xff;
- if (gsc_i2c_write(GSC_SC_ADDR, 6, 1, ®, 1))
- goto error;
- if (gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, ®, 1))
- goto error;
- reg |= (1 << 2);
- if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, ®, 1))
- goto error;
- reg &= ~(1 << 2);
- reg |= 0x3;
- if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, ®, 1))
- goto error;
-
- return CMD_RET_SUCCESS;
-
-error:
- printf("i2c error\n");
- return CMD_RET_FAILURE;
-}
-
-static int do_gsc_wd(struct cmd_tbl *cmdtp, int flag, int argc,
- char *const argv[])
-{
- unsigned char reg;
-
- if (argc < 2)
- return CMD_RET_USAGE;
-
- if (strcasecmp(argv[1], "enable") == 0) {
- int timeout = 0;
-
- if (argc > 2)
- timeout = dectoul(argv[2], NULL);
- if (gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, ®, 1))
- return CMD_RET_FAILURE;
- reg &= ~((1 << GSC_SC_CTRL1_WDEN) | (1 << GSC_SC_CTRL1_WDTIME));
- if (timeout == 60)
- reg |= (1 << GSC_SC_CTRL1_WDTIME);
- else
- timeout = 30;
- reg |= (1 << GSC_SC_CTRL1_WDEN);
- if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, ®, 1))
- return CMD_RET_FAILURE;
- printf("GSC Watchdog enabled with timeout=%d seconds\n",
- timeout);
- } else if (strcasecmp(argv[1], "disable") == 0) {
- if (gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, ®, 1))
- return CMD_RET_FAILURE;
- reg &= ~((1 << GSC_SC_CTRL1_WDEN) | (1 << GSC_SC_CTRL1_WDTIME));
- if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, ®, 1))
- return CMD_RET_FAILURE;
- printf("GSC Watchdog disabled\n");
- } else {
- return CMD_RET_USAGE;
- }
- return CMD_RET_SUCCESS;
-}
-
-static int do_gsc(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
-{
- if (argc < 2)
- return gsc_info(1);
-
- if (strcasecmp(argv[1], "wd") == 0)
- return do_gsc_wd(cmdtp, flag, --argc, ++argv);
- else if (strcasecmp(argv[1], "sleep") == 0)
- return do_gsc_sleep(cmdtp, flag, --argc, ++argv);
-
- return CMD_RET_USAGE;
-}
-
-U_BOOT_CMD(
- gsc, 4, 1, do_gsc, "GSC configuration",
- "[wd enable [30|60]]|[wd disable]|[sleep <secs>]\n"
- );
-
-#endif /* CONFIG_CMD_GSC */
deleted file mode 100644
@@ -1,72 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (C) 2013 Gateworks Corporation
- *
- * Author: Tim Harvey <tharvey@gateworks.com>
- */
-
-#ifndef __ASSEMBLY__
-
-/* i2c slave addresses */
-#define GSC_SC_ADDR 0x20
-#define GSC_RTC_ADDR 0x68
-#define GSC_HWMON_ADDR 0x29
-#define GSC_EEPROM_ADDR 0x51
-
-/* System Controller registers */
-enum {
- GSC_SC_CTRL0 = 0x00,
- GSC_SC_CTRL1 = 0x01,
- GSC_SC_STATUS = 0x0a,
- GSC_SC_FWCRC = 0x0c,
- GSC_SC_FWVER = 0x0e,
-};
-
-/* System Controller Control1 bits */
-enum {
- GSC_SC_CTRL1_WDTIME = 4, /* 1 = 60s timeout, 0 = 30s timeout */
- GSC_SC_CTRL1_WDEN = 5, /* 1 = enable, 0 = disable */
- GSC_SC_CTRL1_WDDIS = 7, /* 1 = disable boot watchdog */
-};
-
-/* System Controller Interrupt bits */
-enum {
- GSC_SC_IRQ_PB = 0, /* Pushbutton switch */
- GSC_SC_IRQ_SECURE = 1, /* Secure Key erase operation complete */
- GSC_SC_IRQ_EEPROM_WP = 2, /* EEPROM write violation */
- GSC_SC_IRQ_GPIO = 4, /* GPIO change */
- GSC_SC_IRQ_TAMPER = 5, /* Tamper detect */
- GSC_SC_IRQ_WATCHDOG = 6, /* Watchdog trip */
- GSC_SC_IRQ_PBLONG = 7, /* Pushbutton long hold */
-};
-
-/* Hardware Monitor registers */
-enum {
- GSC_HWMON_TEMP = 0x00,
- GSC_HWMON_VIN = 0x02,
- GSC_HWMON_VDD_3P3 = 0x05,
- GSC_HWMON_VBATT = 0x08,
- GSC_HWMON_VDD_5P0 = 0x0b,
- GSC_HWMON_VDD_CORE = 0x0e,
- GSC_HWMON_VDD_SOC = 0x11,
- GSC_HWMON_VDD_HIGH = 0x14,
- GSC_HWMON_VDD_DDR = 0x17,
- GSC_HWMON_VDD_EXT = 0x1a,
- GSC_HWMON_VDD_1P8 = 0x1d,
- GSC_HWMON_VDD_IO2 = 0x20,
- GSC_HWMON_VDD_2P5 = 0x23,
- GSC_HWMON_VDD_IO3 = 0x26,
- GSC_HWMON_VDD_IO4 = 0x29,
-};
-
-/*
- * I2C transactions to the GSC are done via these functions which
- * perform retries in the case of a busy GSC NAK'ing the transaction
- */
-int gsc_i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len);
-int gsc_i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len);
-int gsc_info(int verbose);
-int gsc_boot_wd_disable(void);
-const char *gsc_get_dtb_name(int level, char *buf, int sz);
-struct udevice *i2c_get_dev(int busno, int slave);
-#endif
@@ -5,40 +5,29 @@
* Author: Tim Harvey <tharvey@gateworks.com>
*/
+#include <command.h>
#include <common.h>
+#include <fdt_support.h>
+#include <gsc.h>
+#include <hwconfig.h>
+#include <i2c.h>
+#include <miiphy.h>
+#include <mtd_node.h>
#include <asm/arch/clock.h>
#include <asm/arch/crm_regs.h>
#include <asm/arch/mx6-pins.h>
#include <asm/arch/mxc_hdmi.h>
#include <asm/arch/sys_proto.h>
-#include <asm/global_data.h>
-#include <asm/gpio.h>
#include <asm/mach-imx/boot_mode.h>
#include <asm/mach-imx/video.h>
-#include <asm/setup.h>
-#include <env.h>
-#include <hwconfig.h>
+#include <jffs2/load_kernel.h>
#include <linux/ctype.h>
-#include <miiphy.h>
-#include <mtd_node.h>
#include <linux/delay.h>
-#include <power/pmic.h>
-#include <fdt_support.h>
-#include <jffs2/load_kernel.h>
-#include "gsc.h"
#include "common.h"
DECLARE_GLOBAL_DATA_PTR;
-
-/*
- * EEPROM board info struct populated by read_eeprom so that we only have to
- * read it once.
- */
-struct ventana_board_info ventana_info;
-static int board_type;
-
/* configure eth0 PHY board-specific LED behavior */
int board_phy_config(struct phy_device *phydev)
{
@@ -482,9 +471,12 @@ int board_init(void)
gd->bd->bi_boot_params = PHYS_SDRAM + 0x100;
/* read Gateworks EEPROM into global struct (used later) */
- board_type = read_eeprom(CONFIG_I2C_GSC, &ventana_info);
+ board_type = read_eeprom(&ventana_info);
- setup_iomux_gpio(board_type, &ventana_info);
+ setup_iomux_gpio(board_type);
+
+ /* show GSC details */
+ run_command("gsc", 0);
return 0;
}
@@ -517,7 +509,6 @@ int board_fit_config_name_match(const char *name)
int checkboard(void)
{
struct ventana_board_info *info = &ventana_info;
- unsigned char buf[4];
const char *p;
int quiet; /* Quiet or minimal output mode */
@@ -541,15 +532,6 @@ int checkboard(void)
if (quiet)
return 0;
- /* Display GSC firmware revision/CRC/status */
- gsc_info(0);
-
- /* Display RTC */
- if (!gsc_i2c_read(GSC_RTC_ADDR, 0x00, 1, buf, 4)) {
- printf("RTC: %d\n",
- buf[0] | buf[1]<<8 | buf[2]<<16 | buf[3]<<24);
- }
-
return 0;
}
#endif
@@ -6,26 +6,22 @@
#include <common.h>
#include <env.h>
+#include <gsc.h>
#include <hang.h>
+#include <i2c.h>
#include <init.h>
-#include <log.h>
-#include <asm/io.h>
+#include <spl.h>
#include <asm/arch/crm_regs.h>
#include <asm/arch/mx6-ddr.h>
#include <asm/arch/mx6-pins.h>
#include <asm/arch/sys_proto.h>
-#include <asm/mach-imx/boot_mode.h>
-#include <asm/mach-imx/iomux-v3.h>
#include <asm/mach-imx/mxc_i2c.h>
-#include <env.h>
-#include <i2c.h>
-#include <spl.h>
+#include <linux/delay.h>
+#include <power/mp5416.h>
#include <power/pmic.h>
-#include <power/ltc3676_pmic.h>
#include <power/pfuze100_pmic.h>
-#include <power/mp5416.h>
+#include <power/ltc3676_pmic.h>
-#include "gsc.h"
#include "common.h"
#define RTT_NOM_120OHM /* use 120ohm Rtt_nom vs 60ohm (lower power) */
@@ -778,8 +774,6 @@ static void setup_ventana_i2c(int i2c)
void setup_pmic(void)
{
struct pmic *p;
- struct ventana_board_info ventana_info;
- int board = read_eeprom(CONFIG_I2C_GSC, &ventana_info);
const int i2c_pmic = 1;
u32 reg;
char rev;
@@ -817,7 +811,7 @@ void setup_pmic(void)
reg |= (SWBST_5_00V | (SWBST_MODE_AUTO << SWBST_MODE_SHIFT));
pmic_reg_write(p, PFUZE100_SWBSTCON1, reg);
- if (board == GW54xx && (rev == 'G')) {
+ if (board_type == GW54xx && (rev == 'G')) {
/* Disable VGEN5 */
pmic_reg_write(p, PFUZE100_VGEN5VOL, 0);
@@ -873,7 +867,7 @@ void setup_pmic(void)
* is a bit shy of the Vmin of 1350mV in the datasheet
* for LDO enabled mode but is as high as we can go.
*/
- switch (board) {
+ switch (board_type) {
case GW560x:
/* mask PGOOD during SW3 transition */
pmic_reg_write(p, LTC3676_DVB3B,
@@ -931,7 +925,7 @@ void setup_pmic(void)
/* configure MP5416 PMIC */
else if (!i2c_probe(0x69)) {
puts("PMIC: MP5416\n");
- switch (board) {
+ switch (board_type) {
case GW5910:
/* SW1: VDD_ARM 1.2V -> (1.275 to 1.475) */
reg = MP5416_VSET_EN | MP5416_VSET_SW1_SVAL(1475000);
@@ -974,11 +968,23 @@ void board_init_f(ulong dummy)
/* UART clocks enabled and gd valid - init serial console */
preloader_console_init();
+ /*
+ * On a board with a missing/depleted backup battery for GSC, the
+ * board may be ready to probe the GSC before its firmware is
+ * running. We will wait here indefinately for the GSC/EEPROM.
+ */
+ while (1) {
+ if (!i2c_set_bus_num(BOARD_EEPROM_BUSNO) &&
+ !i2c_probe(BOARD_EEPROM_ADDR))
+ break;
+ mdelay(1);
+ }
+
/* read/validate EEPROM info to determine board model and SDRAM cfg */
- board_model = read_eeprom(CONFIG_I2C_GSC, &ventana_info);
+ board_model = read_eeprom(&ventana_info);
/* configure model-specific gpio */
- setup_iomux_gpio(board_model, &ventana_info);
+ setup_iomux_gpio(board_model);
/* provide some some default: 32bit 128MB */
if (GW_UNKNOWN == board_model)
@@ -1006,7 +1012,6 @@ void board_boot_order(u32 *spl_boot_list)
/* called from board_init_r after gd setup if CONFIG_SPL_BOARD_INIT defined */
/* its our chance to print info about boot device */
-static int board_type;
void spl_board_init(void)
{
u32 boot_device;
@@ -1015,7 +1020,7 @@ void spl_board_init(void)
boot_device = spl_boot_device();
/* read eeprom again now that we have gd */
- board_type = read_eeprom(CONFIG_I2C_GSC, &ventana_info);
+ board_type = read_eeprom(&ventana_info);
if (board_type == GW_UNKNOWN)
hang();
@@ -14,11 +14,11 @@ CONFIG_SYS_I2C_MXC_I2C1=y
CONFIG_SYS_I2C_MXC_I2C2=y
CONFIG_SYS_I2C_MXC_I2C3=y
CONFIG_CMD_EECONFIG=y
-CONFIG_CMD_GSC=y
CONFIG_DEFAULT_DEVICE_TREE="imx6q-gw54xx"
CONFIG_SPL_TEXT_BASE=0x00908000
CONFIG_SPL_MMC=y
CONFIG_SPL_SERIAL=y
+CONFIG_SPL_DRIVERS_MISC=y
CONFIG_SPL_STACK_R_ADDR=0x18000000
CONFIG_SPL=y
CONFIG_ENV_OFFSET_REDUND=0xD1400
@@ -14,11 +14,11 @@ CONFIG_SYS_I2C_MXC_I2C1=y
CONFIG_SYS_I2C_MXC_I2C2=y
CONFIG_SYS_I2C_MXC_I2C3=y
CONFIG_CMD_EECONFIG=y
-CONFIG_CMD_GSC=y
CONFIG_DEFAULT_DEVICE_TREE="imx6q-gw54xx"
CONFIG_SPL_TEXT_BASE=0x00908000
CONFIG_SPL_MMC=y
CONFIG_SPL_SERIAL=y
+CONFIG_SPL_DRIVERS_MISC=y
CONFIG_SPL_STACK_R_ADDR=0x18000000
CONFIG_SPL=y
CONFIG_ENV_OFFSET_REDUND=0xD1400
@@ -14,11 +14,11 @@ CONFIG_SYS_I2C_MXC_I2C1=y
CONFIG_SYS_I2C_MXC_I2C2=y
CONFIG_SYS_I2C_MXC_I2C3=y
CONFIG_CMD_EECONFIG=y
-CONFIG_CMD_GSC=y
CONFIG_DEFAULT_DEVICE_TREE="imx6q-gw54xx"
CONFIG_SPL_TEXT_BASE=0x00908000
CONFIG_SPL_MMC=y
CONFIG_SPL_SERIAL=y
+CONFIG_SPL_DRIVERS_MISC=y
CONFIG_SPL_STACK_R_ADDR=0x18000000
CONFIG_SPL=y
CONFIG_ENV_OFFSET_REDUND=0x1080000
@@ -31,9 +31,6 @@
#undef CONFIG_SYS_BOOTM_LEN
#define CONFIG_SYS_BOOTM_LEN (64 << 20)
-/* I2C Configs */
-#define CONFIG_I2C_GSC 0
-
/* MMC Configs */
#define CONFIG_SYS_FSL_ESDHC_ADDR 0
@@ -429,7 +429,6 @@ CONFIG_HUSH_INIT_VAR
CONFIG_HWCONFIG
CONFIG_HW_ENV_SETTINGS
CONFIG_I2C_ENV_EEPROM_BUS
-CONFIG_I2C_GSC
CONFIG_I2C_MULTI_BUS
CONFIG_I2C_MVTWSI
CONFIG_I2C_MVTWSI_BASE
Use the common GSC driver. This allows us to do some additional cleanup: - use the GSC driver functions - move waiting for the EEPROM to the SPL int (it will always be ready after this) - move eeprom functions into eeprom file and elimate GSC_I2C_BUS - eliminate some redundant EEPROM reads (the EEPROM must be read in SPL before relocation, in SPL after relocation, and in U-Boot init. All subsequent uses can use the global structure) - remove unnecessary header files and alphabatize includes Signed-off-by: Tim Harvey <tharvey@gateworks.com> --- arch/arm/mach-imx/mx6/Kconfig | 2 + board/gateworks/gw_ventana/Kconfig | 8 - board/gateworks/gw_ventana/Makefile | 2 +- board/gateworks/gw_ventana/common.c | 16 +- board/gateworks/gw_ventana/common.h | 4 +- board/gateworks/gw_ventana/eeprom.c | 233 +++++++-- .../gw_ventana/{ventana_eeprom.h => eeprom.h} | 16 +- board/gateworks/gw_ventana/gsc.c | 471 ------------------ board/gateworks/gw_ventana/gsc.h | 72 --- board/gateworks/gw_ventana/gw_ventana.c | 44 +- board/gateworks/gw_ventana/gw_ventana_spl.c | 43 +- configs/gwventana_emmc_defconfig | 2 +- configs/gwventana_gw5904_defconfig | 2 +- configs/gwventana_nand_defconfig | 2 +- include/configs/gw_ventana.h | 3 - scripts/config_whitelist.txt | 1 - 16 files changed, 266 insertions(+), 655 deletions(-) rename board/gateworks/gw_ventana/{ventana_eeprom.h => eeprom.h} (82%) delete mode 100644 board/gateworks/gw_ventana/gsc.c delete mode 100644 board/gateworks/gw_ventana/gsc.h