uboot/board/Synology/ds414/cmd_syno.c
<<
>>
Prefs
   1/*
   2 * Commands to deal with Synology specifics.
   3 *
   4 * Copyright (C) 2015  Phil Sutter <phil@nwl.cc>
   5 *
   6 * SPDX-License-Identifier:     GPL-2.0+
   7 */
   8
   9#include <common.h>
  10#include <div64.h>
  11#include <spi.h>
  12#include <spi_flash.h>
  13#include <linux/mtd/mtd.h>
  14
  15#include <asm/io.h>
  16#include "../drivers/ddr/marvell/axp/ddr3_init.h"
  17
  18#define ETH_ALEN                6
  19#define ETHADDR_MAX             4
  20#define SYNO_SN_TAG             "SN="
  21#define SYNO_CHKSUM_TAG         "CHK="
  22
  23
  24static int do_syno_populate(int argc, char * const argv[])
  25{
  26        unsigned int bus = CONFIG_SF_DEFAULT_BUS;
  27        unsigned int cs = CONFIG_SF_DEFAULT_CS;
  28        unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
  29        unsigned int mode = CONFIG_SF_DEFAULT_MODE;
  30        struct spi_flash *flash;
  31        unsigned long addr = 0x80000; /* XXX: parameterize this? */
  32        loff_t offset = 0x007d0000;
  33        loff_t len = 0x00010000;
  34        char *buf, *bufp;
  35        char var[128];
  36        char val[128];
  37        int ret, n;
  38
  39        /* XXX: arg parsing to select flash here? */
  40
  41        flash = spi_flash_probe(bus, cs, speed, mode);
  42        if (!flash) {
  43                printf("Failed to initialize SPI flash at %u:%u\n", bus, cs);
  44                return 1;
  45        }
  46
  47        buf = map_physmem(addr, len, MAP_WRBACK);
  48        if (!buf) {
  49                puts("Failed to map physical memory\n");
  50                return 1;
  51        }
  52
  53        ret = spi_flash_read(flash, offset, len, buf);
  54        if (ret) {
  55                puts("Failed to read from SPI flash\n");
  56                goto out_unmap;
  57        }
  58
  59        for (n = 0; n < ETHADDR_MAX; n++) {
  60                char ethaddr[ETH_ALEN];
  61                int i, sum = 0;
  62                unsigned char csum = 0;
  63
  64                for (i = 0, bufp = buf + n * 7; i < ETH_ALEN; i++) {
  65                        sum += bufp[i];
  66                        csum += bufp[i];
  67                        ethaddr[i] = bufp[i];
  68                }
  69                if (!sum)               /* MAC address empty */
  70                        continue;
  71                if (csum != bufp[i]) {  /* seventh byte is checksum value */
  72                        printf("Invalid MAC address for interface %d!\n", n);
  73                        continue;
  74                }
  75                if (n == 0)
  76                        sprintf(var, "ethaddr");
  77                else
  78                        sprintf(var, "eth%daddr", n);
  79                snprintf(val, sizeof(val) - 1,
  80                         "%02x:%02x:%02x:%02x:%02x:%02x",
  81                         ethaddr[0], ethaddr[1], ethaddr[2],
  82                         ethaddr[3], ethaddr[4], ethaddr[5]);
  83                printf("parsed %s = %s\n", var, val);
  84                setenv(var, val);
  85        }
  86        if (!strncmp(buf + 32, SYNO_SN_TAG, strlen(SYNO_SN_TAG))) {
  87                char *snp, *csump;
  88                int csum = 0;
  89                unsigned long c;
  90
  91                snp = bufp = buf + 32 + strlen(SYNO_SN_TAG);
  92                for (n = 0; bufp[n] && bufp[n] != ','; n++)
  93                        csum += bufp[n];
  94                bufp[n] = '\0';
  95
  96                /* should come right after, but you never know */
  97                bufp = strstr(bufp + n + 1, SYNO_CHKSUM_TAG);
  98                if (!bufp) {
  99                        printf("Serial number checksum tag missing!\n");
 100                        goto out_unmap;
 101                }
 102
 103                csump = bufp += strlen(SYNO_CHKSUM_TAG);
 104                for (n = 0; bufp[n] && bufp[n] != ','; n++)
 105                        ;
 106                bufp[n] = '\0';
 107
 108                if (strict_strtoul(csump, 10, &c) || c != csum) {
 109                        puts("Invalid serial number found!\n");
 110                        ret = 1;
 111                        goto out_unmap;
 112                }
 113                printf("parsed SN = %s\n", snp);
 114                setenv("SN", snp);
 115        } else {        /* old style format */
 116                unsigned char csum = 0;
 117
 118                for (n = 0, bufp = buf + 32; n < 10; n++)
 119                        csum += bufp[n];
 120
 121                if (csum != bufp[n]) {
 122                        puts("Invalid serial number found!\n");
 123                        ret = 1;
 124                        goto out_unmap;
 125                }
 126                bufp[n] = '\0';
 127                printf("parsed SN = %s\n", buf + 32);
 128                setenv("SN", buf + 32);
 129        }
 130out_unmap:
 131        unmap_physmem(buf, len);
 132        return ret;
 133}
 134
 135/* map bit position to function in POWER_MNG_CTRL_REG */
 136static const char * const pwr_mng_bit_func[] = {
 137        "audio",
 138        "ge3", "ge2", "ge1", "ge0",
 139        "pcie00", "pcie01", "pcie02", "pcie03",
 140        "pcie10", "pcie11", "pcie12", "pcie13",
 141        "bp",
 142        "sata0_link", "sata0_core",
 143        "lcd",
 144        "sdio",
 145        "usb0", "usb1", "usb2",
 146        "idma", "xor0", "crypto",
 147        NULL,
 148        "tdm",
 149        "pcie20", "pcie30",
 150        "xor1",
 151        "sata1_link", "sata1_core",
 152        NULL,
 153};
 154
 155static int do_syno_clk_gate(int argc, char * const argv[])
 156{
 157        u32 pwr_mng_ctrl_reg = reg_read(POWER_MNG_CTRL_REG);
 158        const char *func, *state;
 159        int i, val;
 160
 161        if (argc < 2)
 162                return -1;
 163
 164        if (!strcmp(argv[1], "get")) {
 165                puts("Clock Gating:\n");
 166                for (i = 0; i < 32; i++) {
 167                        func = pwr_mng_bit_func[i];
 168                        if (!func)
 169                                continue;
 170                        state = pwr_mng_ctrl_reg & (1 << i) ?  "ON" : "OFF";
 171                        printf("%s:\t\t%s\n", func, state);
 172                }
 173                return 0;
 174        }
 175        if (argc < 4)
 176                return -1;
 177        if (!strcmp(argv[1], "set")) {
 178                func = argv[2];
 179                state = argv[3];
 180                for (i = 0; i < 32; i++) {
 181                        if (!pwr_mng_bit_func[i])
 182                                continue;
 183                        if (!strcmp(func, pwr_mng_bit_func[i]))
 184                                break;
 185                }
 186                if (i == 32) {
 187                        printf("Error: name '%s' not known\n", func);
 188                        return -1;
 189                }
 190                val = state[0] != '0';
 191                pwr_mng_ctrl_reg |= (val << i);
 192                pwr_mng_ctrl_reg &= ~(!val << i);
 193                reg_write(POWER_MNG_CTRL_REG, pwr_mng_ctrl_reg);
 194        }
 195        return 0;
 196}
 197
 198static int do_syno(cmd_tbl_t *cmdtp, int flag,
 199                   int argc, char * const argv[])
 200{
 201        const char *cmd;
 202        int ret = 0;
 203
 204        if (argc < 2)
 205                goto usage;
 206
 207        cmd = argv[1];
 208        --argc;
 209        ++argv;
 210
 211        if (!strcmp(cmd, "populate_env"))
 212                ret = do_syno_populate(argc, argv);
 213        else if (!strcmp(cmd, "clk_gate"))
 214                ret = do_syno_clk_gate(argc, argv);
 215
 216        if (ret != -1)
 217                return ret;
 218usage:
 219        return CMD_RET_USAGE;
 220}
 221
 222U_BOOT_CMD(
 223        syno, 5, 1, do_syno,
 224        "Synology specific commands",
 225        "populate_env                 - Read vendor data from SPI flash into environment\n"
 226        "clk_gate (get|set name 1|0)  - Manage clock gating\n"
 227);
 228