uboot/board/gateworks/gw_ventana/gsc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2013 Gateworks Corporation
   4 *
   5 * Author: Tim Harvey <tharvey@gateworks.com>
   6 */
   7
   8#include <common.h>
   9#include <command.h>
  10#include <log.h>
  11#include <linux/delay.h>
  12#include <linux/errno.h>
  13#include <common.h>
  14#include <i2c.h>
  15#include <linux/ctype.h>
  16
  17#include "ventana_eeprom.h"
  18#include "gsc.h"
  19
  20/*
  21 * The Gateworks System Controller will fail to ACK a master transaction if
  22 * it is busy, which can occur during its 1HZ timer tick while reading ADC's.
  23 * When this does occur, it will never be busy long enough to fail more than
  24 * 2 back-to-back transfers.  Thus we wrap i2c_read and i2c_write with
  25 * 3 retries.
  26 */
  27int gsc_i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len)
  28{
  29        int retry = 3;
  30        int n = 0;
  31        int ret;
  32
  33        while (n++ < retry) {
  34                ret = i2c_read(chip, addr, alen, buf, len);
  35                if (!ret)
  36                        break;
  37                debug("%s: 0x%02x 0x%02x retry%d: %d\n", __func__, chip, addr,
  38                      n, ret);
  39                if (ret != -ENODEV)
  40                        break;
  41                mdelay(10);
  42        }
  43        return ret;
  44}
  45
  46int gsc_i2c_write(uchar chip, uint addr, int alen, uchar *buf, int len)
  47{
  48        int retry = 3;
  49        int n = 0;
  50        int ret;
  51
  52        while (n++ < retry) {
  53                ret = i2c_write(chip, addr, alen, buf, len);
  54                if (!ret)
  55                        break;
  56                debug("%s: 0x%02x 0x%02x retry%d: %d\n", __func__, chip, addr,
  57                      n, ret);
  58                if (ret != -ENODEV)
  59                        break;
  60                mdelay(10);
  61        }
  62        mdelay(100);
  63        return ret;
  64}
  65
  66static void read_hwmon(const char *name, uint reg, uint size)
  67{
  68        unsigned char buf[3];
  69        uint ui;
  70
  71        printf("%-8s:", name);
  72        memset(buf, 0, sizeof(buf));
  73        if (gsc_i2c_read(GSC_HWMON_ADDR, reg, 1, buf, size)) {
  74                puts("fRD\n");
  75        } else {
  76                ui = buf[0] | (buf[1]<<8) | (buf[2]<<16);
  77                if (size == 2 && ui > 0x8000)
  78                        ui -= 0xffff;
  79                if (ui == 0xffffff)
  80                        puts("invalid\n");
  81                else
  82                        printf("%d\n", ui);
  83        }
  84}
  85
  86int gsc_info(int verbose)
  87{
  88        unsigned char buf[16];
  89
  90        i2c_set_bus_num(0);
  91        if (gsc_i2c_read(GSC_SC_ADDR, 0, 1, buf, 16))
  92                return CMD_RET_FAILURE;
  93
  94        printf("GSC:   v%d", buf[GSC_SC_FWVER]);
  95        printf(" 0x%04x", buf[GSC_SC_FWCRC] | buf[GSC_SC_FWCRC+1]<<8);
  96        printf(" WDT:%sabled", (buf[GSC_SC_CTRL1] & (1<<GSC_SC_CTRL1_WDEN))
  97                ? "en" : "dis");
  98        if (buf[GSC_SC_STATUS] & (1 << GSC_SC_IRQ_WATCHDOG)) {
  99                buf[GSC_SC_STATUS] &= ~(1 << GSC_SC_IRQ_WATCHDOG);
 100                puts(" WDT_RESET");
 101                gsc_i2c_write(GSC_SC_ADDR, GSC_SC_STATUS, 1,
 102                              &buf[GSC_SC_STATUS], 1);
 103        }
 104        if (!gsc_i2c_read(GSC_HWMON_ADDR, GSC_HWMON_TEMP, 1, buf, 2)) {
 105                int ui = buf[0] | buf[1]<<8;
 106                if (ui > 0x8000)
 107                        ui -= 0xffff;
 108                printf(" board temp at %dC", ui / 10);
 109        }
 110        puts("\n");
 111        if (!verbose)
 112                return CMD_RET_SUCCESS;
 113
 114        read_hwmon("Temp",     GSC_HWMON_TEMP, 2);
 115        read_hwmon("VIN",      GSC_HWMON_VIN, 3);
 116        read_hwmon("VBATT",    GSC_HWMON_VBATT, 3);
 117        read_hwmon("VDD_3P3",  GSC_HWMON_VDD_3P3, 3);
 118        read_hwmon("VDD_ARM",  GSC_HWMON_VDD_CORE, 3);
 119        read_hwmon("VDD_SOC",  GSC_HWMON_VDD_SOC, 3);
 120        read_hwmon("VDD_HIGH", GSC_HWMON_VDD_HIGH, 3);
 121        read_hwmon("VDD_DDR",  GSC_HWMON_VDD_DDR, 3);
 122        read_hwmon("VDD_5P0",  GSC_HWMON_VDD_5P0, 3);
 123        if (strncasecmp((const char*) ventana_info.model, "GW553", 5))
 124                read_hwmon("VDD_2P5",  GSC_HWMON_VDD_2P5, 3);
 125        read_hwmon("VDD_1P8",  GSC_HWMON_VDD_1P8, 3);
 126        read_hwmon("VDD_IO2",  GSC_HWMON_VDD_IO2, 3);
 127        switch (ventana_info.model[3]) {
 128        case '1': /* GW51xx */
 129                read_hwmon("VDD_IO3",  GSC_HWMON_VDD_IO4, 3); /* -C rev */
 130                break;
 131        case '2': /* GW52xx */
 132                break;
 133        case '3': /* GW53xx */
 134                read_hwmon("VDD_IO4",  GSC_HWMON_VDD_IO4, 3); /* -C rev */
 135                read_hwmon("VDD_GPS",  GSC_HWMON_VDD_IO3, 3);
 136                break;
 137        case '4': /* GW54xx */
 138                read_hwmon("VDD_IO3",  GSC_HWMON_VDD_IO4, 3); /* -C rev */
 139                read_hwmon("VDD_GPS",  GSC_HWMON_VDD_IO3, 3);
 140                break;
 141        case '5': /* GW55xx */
 142                break;
 143        case '6': /* GW560x */
 144                read_hwmon("VDD_IO4",  GSC_HWMON_VDD_IO4, 3);
 145                read_hwmon("VDD_GPS",  GSC_HWMON_VDD_IO3, 3);
 146                break;
 147        case '9': /* GW590x */
 148                read_hwmon("AMONBMON",  GSC_HWMON_VDD_IO3, 3);
 149                read_hwmon("BAT_VOLT",  GSC_HWMON_VDD_EXT, 3);
 150                read_hwmon("BAT_TEMP",  GSC_HWMON_VDD_IO4, 2);
 151        }
 152        return 0;
 153}
 154
 155/*
 156 *  The Gateworks System Controller implements a boot
 157 *  watchdog (always enabled) as a workaround for IMX6 boot related
 158 *  errata such as:
 159 *    ERR005768 - no fix scheduled
 160 *    ERR006282 - fixed in silicon r1.2
 161 *    ERR007117 - fixed in silicon r1.3
 162 *    ERR007220 - fixed in silicon r1.3
 163 *    ERR007926 - no fix scheduled
 164 *  see http://cache.freescale.com/files/32bit/doc/errata/IMX6DQCE.pdf
 165 *
 166 * Disable the boot watchdog
 167 */
 168int gsc_boot_wd_disable(void)
 169{
 170        u8 reg;
 171
 172        i2c_set_bus_num(CONFIG_I2C_GSC);
 173        if (!gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1)) {
 174                reg |= (1 << GSC_SC_CTRL1_WDDIS);
 175                if (!gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
 176                        return 0;
 177        }
 178        puts("Error: could not disable GSC Watchdog\n");
 179        return 1;
 180}
 181
 182#if defined(CONFIG_CMD_GSC) && !defined(CONFIG_SPL_BUILD)
 183static int do_gsc_sleep(struct cmd_tbl *cmdtp, int flag, int argc,
 184                        char *const argv[])
 185{
 186        unsigned char reg;
 187        unsigned long secs = 0;
 188
 189        if (argc < 2)
 190                return CMD_RET_USAGE;
 191
 192        secs = simple_strtoul(argv[1], NULL, 10);
 193        printf("GSC Sleeping for %ld seconds\n", secs);
 194
 195        i2c_set_bus_num(0);
 196        reg = (secs >> 24) & 0xff;
 197        if (gsc_i2c_write(GSC_SC_ADDR, 9, 1, &reg, 1))
 198                goto error;
 199        reg = (secs >> 16) & 0xff;
 200        if (gsc_i2c_write(GSC_SC_ADDR, 8, 1, &reg, 1))
 201                goto error;
 202        reg = (secs >> 8) & 0xff;
 203        if (gsc_i2c_write(GSC_SC_ADDR, 7, 1, &reg, 1))
 204                goto error;
 205        reg = secs & 0xff;
 206        if (gsc_i2c_write(GSC_SC_ADDR, 6, 1, &reg, 1))
 207                goto error;
 208        if (gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
 209                goto error;
 210        reg |= (1 << 2);
 211        if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
 212                goto error;
 213        reg &= ~(1 << 2);
 214        reg |= 0x3;
 215        if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
 216                goto error;
 217
 218        return CMD_RET_SUCCESS;
 219
 220error:
 221        printf("i2c error\n");
 222        return CMD_RET_FAILURE;
 223}
 224
 225static int do_gsc_wd(struct cmd_tbl *cmdtp, int flag, int argc,
 226                     char *const argv[])
 227{
 228        unsigned char reg;
 229
 230        if (argc < 2)
 231                return CMD_RET_USAGE;
 232
 233        if (strcasecmp(argv[1], "enable") == 0) {
 234                int timeout = 0;
 235
 236                if (argc > 2)
 237                        timeout = simple_strtoul(argv[2], NULL, 10);
 238                i2c_set_bus_num(0);
 239                if (gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
 240                        return CMD_RET_FAILURE;
 241                reg &= ~((1 << GSC_SC_CTRL1_WDEN) | (1 << GSC_SC_CTRL1_WDTIME));
 242                if (timeout == 60)
 243                        reg |= (1 << GSC_SC_CTRL1_WDTIME);
 244                else
 245                        timeout = 30;
 246                reg |= (1 << GSC_SC_CTRL1_WDEN);
 247                if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
 248                        return CMD_RET_FAILURE;
 249                printf("GSC Watchdog enabled with timeout=%d seconds\n",
 250                       timeout);
 251        } else if (strcasecmp(argv[1], "disable") == 0) {
 252                i2c_set_bus_num(0);
 253                if (gsc_i2c_read(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
 254                        return CMD_RET_FAILURE;
 255                reg &= ~((1 << GSC_SC_CTRL1_WDEN) | (1 << GSC_SC_CTRL1_WDTIME));
 256                if (gsc_i2c_write(GSC_SC_ADDR, GSC_SC_CTRL1, 1, &reg, 1))
 257                        return CMD_RET_FAILURE;
 258                printf("GSC Watchdog disabled\n");
 259        } else {
 260                return CMD_RET_USAGE;
 261        }
 262        return CMD_RET_SUCCESS;
 263}
 264
 265static int do_gsc(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 266{
 267        if (argc < 2)
 268                return gsc_info(1);
 269
 270        if (strcasecmp(argv[1], "wd") == 0)
 271                return do_gsc_wd(cmdtp, flag, --argc, ++argv);
 272        else if (strcasecmp(argv[1], "sleep") == 0)
 273                return do_gsc_sleep(cmdtp, flag, --argc, ++argv);
 274
 275        return CMD_RET_USAGE;
 276}
 277
 278U_BOOT_CMD(
 279        gsc, 4, 1, do_gsc, "GSC configuration",
 280        "[wd enable [30|60]]|[wd disable]|[sleep <secs>]\n"
 281        );
 282
 283#endif /* CONFIG_CMD_GSC */
 284