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