uboot/board/micronas/vct/smc_eeprom.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2008 Stefan Roese <sr@denx.de>, DENX Software Engineering
   3 *
   4 * Copyright 2005, Seagate Technology LLC
   5 *
   6 * See file CREDITS for list of people who contributed to this
   7 * project.
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License version 2 as
  11 * published by the Free Software Foundation.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 *
  23 */
  24
  25#undef DEBUG
  26
  27#include <common.h>
  28#include <command.h>
  29#include <config.h>
  30#include <net.h>
  31
  32#include "vct.h"
  33
  34#define SMSC9118_BASE           CONFIG_DRIVER_SMC911X_BASE
  35#define BYTE_TEST               (SMSC9118_BASE + 0x64)
  36#define GPIO_CFG                (SMSC9118_BASE + 0x88)
  37#define MAC_CSR_CMD             (SMSC9118_BASE + 0xA4)
  38#define  MAC_CSR_CMD_CSR_BUSY   (0x80000000)
  39#define  MAC_CSR_CMD_RNW        (0x40000000)
  40#define  MAC_RD_CMD(reg)        ((reg & 0x000000FF) |                   \
  41                                 (MAC_CSR_CMD_CSR_BUSY | MAC_CSR_CMD_RNW))
  42#define  MAC_WR_CMD(reg)        ((reg & 0x000000FF) |           \
  43                                 (MAC_CSR_CMD_CSR_BUSY))
  44#define MAC_CSR_DATA            (SMSC9118_BASE + 0xA8)
  45#define E2P_CMD                 (SMSC9118_BASE + 0xB0)
  46#define  E2P_CMD_EPC_BUSY_      (0x80000000UL)  /* Self Clearing */
  47#define  E2P_CMD_EPC_CMD_       (0x70000000UL)  /* R/W */
  48#define  E2P_CMD_EPC_CMD_READ_  (0x00000000UL)  /* R/W */
  49#define  E2P_CMD_EPC_CMD_EWDS_  (0x10000000UL)  /* R/W */
  50#define  E2P_CMD_EPC_CMD_EWEN_  (0x20000000UL)  /* R/W */
  51#define  E2P_CMD_EPC_CMD_WRITE_ (0x30000000UL)  /* R/W */
  52#define  E2P_CMD_EPC_CMD_WRAL_  (0x40000000UL)  /* R/W */
  53#define  E2P_CMD_EPC_CMD_ERASE_ (0x50000000UL)  /* R/W */
  54#define  E2P_CMD_EPC_CMD_ERAL_  (0x60000000UL)  /* R/W */
  55#define  E2P_CMD_EPC_CMD_RELOAD_ (0x70000000UL) /* R/W */
  56#define  E2P_CMD_EPC_TIMEOUT_   (0x00000200UL)  /* R */
  57#define  E2P_CMD_MAC_ADDR_LOADED_ (0x00000100UL) /* RO */
  58#define  E2P_CMD_EPC_ADDR_      (0x000000FFUL)  /* R/W */
  59#define E2P_DATA                (SMSC9118_BASE + 0xB4)
  60
  61#define MAC_ADDRH               (0x2)
  62#define MAC_ADDRL               (0x3)
  63
  64#define MAC_TIMEOUT             200
  65
  66#define HIBYTE(word)            ((u8)(((u16)(word)) >> 8))
  67#define LOBYTE(word)            ((u8)(((u16)(word)) & 0x00FFU))
  68#define HIWORD(dword)           ((u16)(((u32)(dword)) >> 16))
  69#define LOWORD(dword)           ((u16)(((u32)(dword)) & 0x0000FFFFUL))
  70
  71static int mac_busy(int req_to)
  72{
  73        int timeout = req_to;
  74
  75        while (timeout--) {
  76                if (!(smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY))
  77                        goto done;
  78        }
  79        return 1;               /* Timeout */
  80
  81done:
  82        return 0;               /* No timeout */
  83}
  84
  85static ulong get_mac_reg(int reg)
  86{
  87        ulong reg_val = 0xffffffff;
  88
  89        if (smc911x_reg_read(MAC_CSR_CMD) & MAC_CSR_CMD_CSR_BUSY) {
  90                printf("get_mac_reg: previous command not complete\n");
  91                goto done;
  92        }
  93
  94        smc911x_reg_write(MAC_CSR_CMD, MAC_RD_CMD(reg));
  95        udelay(10000);
  96
  97        if (mac_busy(MAC_TIMEOUT) == 1) {
  98                printf("get_mac_reg: timeout waiting for response from MAC\n");
  99                goto done;
 100        }
 101
 102        reg_val = smc911x_reg_read(MAC_CSR_DATA);
 103
 104done:
 105        return (reg_val);
 106}
 107
 108static ulong eeprom_enable_access(void)
 109{
 110        ulong gpio;
 111
 112        gpio = smc911x_reg_read(GPIO_CFG);
 113        debug("%s: gpio= 0x%08lx ---> 0x%08lx\n", __func__, gpio,
 114              (gpio & 0xFF0FFFFFUL));
 115
 116        smc911x_reg_write(GPIO_CFG, (gpio & 0xFF0FFFFFUL));
 117        return gpio;
 118}
 119
 120static void eeprom_disable_access(ulong gpio)
 121{
 122        debug("%s: gpio= 0x%08lx\n", __func__, gpio);
 123        smc911x_reg_write(GPIO_CFG, gpio);
 124}
 125
 126static int eeprom_is_mac_address_loaded(void)
 127{
 128        int ret;
 129
 130        ret = smc911x_reg_read(MAC_CSR_CMD) & E2P_CMD_MAC_ADDR_LOADED_;
 131        debug("%s: ret = %x\n", __func__, ret);
 132
 133        return ret;
 134}
 135
 136static int eeprom_read_location(unchar address, u8 *data)
 137{
 138        ulong timeout = 100000;
 139        ulong temp = 0;
 140
 141        if ((temp = smc911x_reg_read(E2P_CMD)) & E2P_CMD_EPC_BUSY_) {
 142                printf("%s: Busy at start, E2P_CMD=0x%08lX\n", __func__, temp);
 143                return 0;
 144        }
 145
 146        smc911x_reg_write(E2P_CMD,
 147                          (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_READ_ |
 148                           ((ulong) address)));
 149
 150        while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
 151                udelay(10);
 152                timeout--;
 153        }
 154
 155        if (timeout == 0) {
 156                printf("Timeout\n");
 157                return 0;
 158        }
 159        (*data) = (unchar) (smc911x_reg_read(E2P_DATA));
 160        debug("%s: ret = %x\n", __func__, (*data));
 161
 162        return 1;
 163}
 164
 165static int eeprom_enable_erase_and_write(void)
 166{
 167        ulong timeout = 100000;
 168
 169        if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) {
 170                printf("%s: Busy at start\n", __func__);
 171                return 0;
 172        }
 173        smc911x_reg_write(E2P_CMD, (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_EWEN_));
 174
 175        while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
 176                udelay(10);
 177                timeout--;
 178        }
 179
 180        if (timeout == 0) {
 181                printf("Timeout[1]\n");
 182                return 0;
 183        }
 184
 185        return 1;
 186}
 187
 188static int eeprom_disable_erase_and_write(void)
 189{
 190        ulong timeout = 100000;
 191
 192        if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) {
 193                printf("%s: Busy at start\n", __func__);
 194                return 0;
 195        }
 196        smc911x_reg_write(E2P_CMD, (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_EWDS_));
 197
 198        while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
 199                udelay(10);
 200                timeout--;
 201        }
 202
 203        if (timeout == 0) {
 204                printf("Timeout[2]\n");
 205                return 0;
 206        }
 207
 208        return 1;
 209}
 210
 211static int eeprom_write_location(unchar address, unchar data)
 212{
 213        ulong timeout = 100000;
 214
 215        debug("%s: address: %x data = %x\n", __func__, address, data);
 216
 217        if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) {
 218                printf("%s: Busy at start\n", __func__);
 219                return 0;
 220        }
 221
 222        smc911x_reg_write(E2P_DATA, ((ulong) data));
 223        smc911x_reg_write(E2P_CMD,
 224                          (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_WRITE_ |
 225                           ((ulong) address)));
 226
 227        while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
 228                udelay(10);
 229                timeout--;
 230        }
 231
 232        if (timeout == 0) {
 233                printf("Timeout[3]\n");
 234                return 0;
 235        }
 236
 237        return 1;
 238}
 239
 240static int eeprom_erase_all(void)
 241{
 242        ulong timeout = 100000;
 243
 244        if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) {
 245                printf("%s: Busy at start\n", __func__);
 246                return 0;
 247        }
 248
 249        smc911x_reg_write(E2P_CMD, (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_ERAL_));
 250
 251        while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
 252                udelay(10);
 253                timeout--;
 254        }
 255
 256        if (timeout == 0) {
 257                printf("Timeout[4]\n");
 258                return 0;
 259        }
 260
 261        return 1;
 262}
 263
 264static int eeprom_reload(void)
 265{
 266        ulong timeout = 100000;
 267
 268        if (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_) {
 269                printf("%s: Busy at start\n", __func__);
 270                return -1;
 271        }
 272        smc911x_reg_write(E2P_CMD,
 273                          (E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_RELOAD_));
 274
 275        while ((timeout > 0) && (smc911x_reg_read(E2P_CMD) & E2P_CMD_EPC_BUSY_)) {
 276                udelay(10);
 277                timeout--;
 278        }
 279
 280        if (timeout == 0)
 281                return 0;
 282
 283        return 1;
 284}
 285
 286static int eeprom_save_mac_address(ulong dwHi16, ulong dwLo32)
 287{
 288        int result = 0;
 289
 290        debug("%s: dwHI: 0x%08lx dwLO: %08lx, \n", __func__, dwHi16, dwLo32);
 291
 292        if (!eeprom_enable_erase_and_write())
 293                goto DONE;
 294        if (!eeprom_erase_all())
 295                goto DONE;
 296        if (!eeprom_write_location(0, 0xA5))
 297                goto DONE;
 298        if (!eeprom_write_location(1, LOBYTE(LOWORD(dwLo32))))
 299                goto DONE;
 300        if (!eeprom_write_location(2, HIBYTE(LOWORD(dwLo32))))
 301                goto DONE;
 302        if (!eeprom_write_location(3, LOBYTE(HIWORD(dwLo32))))
 303                goto DONE;
 304        if (!eeprom_write_location(4, HIBYTE(HIWORD(dwLo32))))
 305                goto DONE;
 306        if (!eeprom_write_location(5, LOBYTE(LOWORD(dwHi16))))
 307                goto DONE;
 308        if (!eeprom_write_location(6, HIBYTE(LOWORD(dwHi16))))
 309                goto DONE;
 310        if (!eeprom_disable_erase_and_write())
 311                goto DONE;
 312
 313        result = 1;
 314
 315DONE:
 316        return result;
 317}
 318
 319static int do_eeprom_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 320{
 321        unchar data = 0, index = 0;
 322        ulong gpio_old_val;
 323
 324        gpio_old_val = eeprom_enable_access();
 325
 326        printf("EEPROM content: \n");
 327        for (index = 0; index < 8; index++) {
 328                if (eeprom_read_location(index, &data))
 329                        printf("%02x ", data);
 330                else
 331                        printf("FAILED");
 332        }
 333
 334        eeprom_disable_access(gpio_old_val);
 335        printf("\n");
 336
 337        return 0;
 338}
 339
 340static int do_eeprom_erase_all(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 341{
 342        eeprom_erase_all();
 343
 344        return 0;
 345}
 346
 347static int do_eeprom_save_mac(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 348{
 349        ulong hi16, lo32;
 350        unchar ethaddr[6], i;
 351        ulong gpio;
 352        char *tmp, *end;
 353
 354        tmp = argv[1];
 355        for (i = 0; i < 6; i++) {
 356                ethaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
 357                if (tmp)
 358                        tmp = (*end) ? end + 1 : end;
 359        }
 360
 361        hi16 = (ethaddr[5] << 8) | (ethaddr[4]);
 362        lo32 = (ethaddr[3] << 24) | (ethaddr[2] << 16) |
 363                (ethaddr[1] << 8) | (ethaddr[0]);
 364
 365        gpio = eeprom_enable_access();
 366
 367        eeprom_save_mac_address(hi16, lo32);
 368
 369        eeprom_reload();
 370
 371        /* Check new values */
 372        if (eeprom_is_mac_address_loaded()) {
 373                ulong mac_hi16, mac_lo32;
 374
 375                mac_hi16 = get_mac_reg(MAC_ADDRH);
 376                mac_lo32 = get_mac_reg(MAC_ADDRL);
 377                printf("New MAC address: %lx, %lx\n", mac_hi16, mac_lo32);
 378        } else {
 379                printf("Address is not reloaded \n");
 380        }
 381        eeprom_disable_access(gpio);
 382
 383        return 0;
 384}
 385
 386U_BOOT_CMD(smcee, 1, 0, do_eeprom_erase_all,
 387           "smcee   - Erase content of SMC EEPROM",);
 388
 389U_BOOT_CMD(smced, 1, 0, do_eeprom_dump,
 390           "smced   - Dump content of SMC EEPROM",);
 391
 392U_BOOT_CMD(smcew, 2, 0, do_eeprom_save_mac,
 393           "smcew   - Write MAC address to SMC EEPROM\n",
 394           "aa:bb:cc:dd:ee:ff  new mac address");
 395