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