uboot/board/voiceblue/eeprom.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2005
   3 * Ladislav Michl, 2N Telekomunikace, michl@2n.cz
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15 * GNU General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20 * MA 02111-1307 USA
  21 *
  22 * Some code shamelessly stolen back from Robin Getz.
  23 */
  24
  25#include <common.h>
  26#include <exports.h>
  27#include <timestamp.h>
  28#include <net.h>
  29#include "../drivers/net/smc91111.h"
  30
  31static struct eth_device dev = {
  32        .iobase = CONFIG_SMC91111_BASE
  33};
  34
  35static u16 read_eeprom_reg(u16 reg)
  36{
  37        int timeout;
  38
  39        SMC_SELECT_BANK(&dev, 2);
  40        SMC_outw(&dev, reg, PTR_REG);
  41
  42        SMC_SELECT_BANK(&dev, 1);
  43        SMC_outw(&dev, SMC_inw(&dev, CTL_REG) | CTL_EEPROM_SELECT |
  44                CTL_RELOAD, CTL_REG);
  45
  46        timeout = 100;
  47
  48        while ((SMC_inw(&dev, CTL_REG) & CTL_RELOAD) && --timeout)
  49                udelay(100);
  50        if (timeout == 0) {
  51                printf("Timeout reading register %02x\n", reg);
  52                return 0;
  53        }
  54
  55        return SMC_inw(&dev, GP_REG);
  56}
  57
  58static int write_eeprom_reg(u16 value, u16 reg)
  59{
  60        int timeout;
  61
  62        SMC_SELECT_BANK(&dev, 2);
  63        SMC_outw(&dev, reg, PTR_REG);
  64
  65        SMC_SELECT_BANK(&dev, 1);
  66
  67        SMC_outw(&dev, value, GP_REG);
  68        SMC_outw(&dev, SMC_inw(&dev, CTL_REG) | CTL_EEPROM_SELECT |
  69                CTL_STORE, CTL_REG);
  70
  71        timeout = 100;
  72
  73        while ((SMC_inw(&dev, CTL_REG) & CTL_STORE) && --timeout)
  74                udelay(100);
  75        if (timeout == 0) {
  76                printf("Timeout writing register %02x\n", reg);
  77                return 0;
  78        }
  79
  80        return 1;
  81}
  82
  83static int write_data(u16 *buf, int len)
  84{
  85        u16 reg = 0x23;
  86
  87        while (len--)
  88                write_eeprom_reg(*buf++, reg++);
  89
  90        return 0;
  91}
  92
  93static int verify_macaddr(char *s)
  94{
  95        u16 reg;
  96        int i, err = 0;
  97
  98        puts("HWaddr: ");
  99        for (i = 0; i < 3; i++) {
 100                reg = read_eeprom_reg(0x20 + i);
 101                printf("%02x:%02x%c", reg & 0xff, reg >> 8, i != 2 ? ':' : '\n');
 102                if (s)
 103                        err |= reg != ((u16 *)s)[i];
 104        }
 105
 106        return err ? 0 : 1;
 107}
 108
 109static int set_mac(char *s)
 110{
 111        int i;
 112        char *e, eaddr[6];
 113
 114        /* turn string into mac value */
 115        for (i = 0; i < 6; i++) {
 116                eaddr[i] = simple_strtoul(s, &e, 16);
 117                s = (*e) ? e+1 : e;
 118        }
 119
 120        for (i = 0; i < 3; i++)
 121                write_eeprom_reg(*(((u16 *)eaddr) + i), 0x20 + i);
 122
 123        return 0;
 124}
 125
 126static int parse_element(char *s, unsigned char *buf, int len)
 127{
 128        int cnt;
 129        char *p, num[3];
 130        unsigned char id;
 131
 132        id = simple_strtoul(s, &p, 16);
 133        if (*p++ != ':')
 134                return -1;
 135        cnt = 2;
 136        num[2] = 0;
 137        for (; *p; p += 2) {
 138                if (p[1] == 0)
 139                        return -2;
 140                if (cnt + 3 > len)
 141                        return -3;
 142                num[0] = p[0];
 143                num[1] = p[1];
 144                buf[cnt++] = simple_strtoul(num, NULL, 16);
 145        }
 146        buf[0] = id;
 147        buf[1] = cnt - 2;
 148
 149        return cnt;
 150}
 151
 152int eeprom(int argc, char * const argv[])
 153{
 154        int i, len, ret;
 155        unsigned char buf[58], *p;
 156
 157        app_startup(argv);
 158        i = get_version();
 159        if (i != XF_VERSION) {
 160                printf("Using ABI version %d, but U-Boot provides %d\n",
 161                        XF_VERSION, i);
 162                return 1;
 163        }
 164
 165        if ((SMC_inw(&dev, BANK_SELECT) & 0xFF00) != 0x3300) {
 166                puts("SMSC91111 not found\n");
 167                return 2;
 168        }
 169
 170        /* Called without parameters - print MAC address */
 171        if (argc < 2) {
 172                verify_macaddr(NULL);
 173                return 0;
 174        }
 175
 176        /* Print help message */
 177        if (argv[1][1] == 'h') {
 178                puts("VoiceBlue EEPROM writer\n"
 179                        "Built: " U_BOOT_DATE " at " U_BOOT_TIME "\n"
 180                        "Usage:\n\t<mac_address> [<element_1>] [<...>]\n");
 181                return 0;
 182        }
 183
 184        /* Try to parse information elements */
 185        len = sizeof(buf);
 186        p = buf;
 187        for (i = 2; i < argc; i++) {
 188                ret = parse_element(argv[i], p, len);
 189                switch (ret) {
 190                case -1:
 191                        printf("Element %d: malformed\n", i - 1);
 192                        return 3;
 193                case -2:
 194                        printf("Element %d: odd character count\n", i - 1);
 195                        return 3;
 196                case -3:
 197                        puts("Out of EEPROM memory\n");
 198                        return 3;
 199                default:
 200                        p += ret;
 201                        len -= ret;
 202                }
 203        }
 204
 205        /* First argument (MAC) is mandatory */
 206        set_mac(argv[1]);
 207        if (verify_macaddr(argv[1])) {
 208                puts("*** HWaddr does not match! ***\n");
 209                return 4;
 210        }
 211
 212        while (len--)
 213                *p++ = 0;
 214
 215        write_data((u16 *)buf, sizeof(buf) >> 1);
 216
 217        return 0;
 218}
 219